blob: 03a5eca04a4d6d6bfd7c747293b644fb18c0d732 [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 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
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ák3b4db242018-10-19 16:11:01 +020014#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
David Sedlák872c7b42018-10-26 13:15:20 +020017#include <string.h>
David Sedlákf824ad52018-10-14 23:58:15 +020018
19#include "common.h"
20#include "context.h"
21#include "libyang.h"
David Sedlák3b4db242018-10-19 16:11:01 +020022#include "xml.h"
23#include "tree_schema_internal.h"
David Sedlákf824ad52018-10-14 23:58:15 +020024
David Sedlák872c7b42018-10-26 13:15:20 +020025enum YIN_ARGUMENT {
26 YIN_ARG_NONE = 0,
27 YIN_ARG_NAME,
28 YIN_ARG_TARGET_NODE,
29 YIN_ARG_MODULE,
30 YIN_ARG_VALUE,
31 YIN_ARG_TEXT,
32 YIN_ARG_CONDITION,
33 YIN_ARG_URI,
34 YIN_ARG_DATE,
35 YIN_ARG_TAG,
36};
David Sedlákf824ad52018-10-14 23:58:15 +020037
David Sedlák872c7b42018-10-26 13:15:20 +020038enum YIN_ARGUMENT
David Sedláke4889912018-11-02 09:52:40 +010039match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020040{
David Sedlák872c7b42018-10-26 13:15:20 +020041 enum YIN_ARGUMENT arg = YIN_ARG_NONE;
42 size_t already_read = 0;
David Sedlák3b4db242018-10-19 16:11:01 +020043
David Sedlákc10e7902018-12-17 02:17:59 +010044#define MOVE_DATA(DATA, COUNT) already_read+=COUNT;
45#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {MOVE_DATA(name, LEN);arg=STMT;}
46#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {MOVE_DATA(name, LEN);
47#define IF_ARG_PREFIX_END }
48
David Sedlák872c7b42018-10-26 13:15:20 +020049 switch(*name) {
50 case 'c':
David Sedlákc10e7902018-12-17 02:17:59 +010051 MOVE_DATA(name, 1);
52 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +020053 break;
David Sedlák872c7b42018-10-26 13:15:20 +020054
55 case 'd':
David Sedlákc10e7902018-12-17 02:17:59 +010056 MOVE_DATA(name, 1);
57 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +020058 break;
David Sedlák872c7b42018-10-26 13:15:20 +020059
60 case 'm':
David Sedlákc10e7902018-12-17 02:17:59 +010061 MOVE_DATA(name, 1);
62 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +020063 break;
64
65 case 'n':
David Sedlákc10e7902018-12-17 02:17:59 +010066 MOVE_DATA(name, 1);
67 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +020068 break;
69
70 case 't':
David Sedlákc10e7902018-12-17 02:17:59 +010071 MOVE_DATA(name, 1);
72 IF_ARG_PREFIX("a", 1)
73 IF_ARG("g", 1, YIN_ARG_TAG)
74 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
75 IF_ARG_PREFIX_END
76 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +020077 break;
David Sedlák872c7b42018-10-26 13:15:20 +020078
79 case 'u':
David Sedlákc10e7902018-12-17 02:17:59 +010080 MOVE_DATA(name, 1);
81 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +020082 break;
David Sedlák872c7b42018-10-26 13:15:20 +020083
84 case 'v':
David Sedlákc10e7902018-12-17 02:17:59 +010085 MOVE_DATA(name, 1);
86 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +020087 break;
88 }
89
David Sedlákc10e7902018-12-17 02:17:59 +010090 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +020091 if (already_read != len) {
92 arg = YIN_ARG_NONE;
93 }
94
95 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +020096}
97
David Sedlák3017da42019-02-15 09:48:04 +010098// LY_ERR
99// parser_belongs_to(struct lyxml_context *xml_ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext **extensions)
100// {
101// enum yang_keyword kw = YANG_NONE;
102// LY_ERR ret = LY_SUCCESS;
103// const char *prefix_out, *name;
104// size_t prefix_len, name_len;
David Sedláka5004e62018-12-16 23:54:47 +0100105
David Sedlák3017da42019-02-15 09:48:04 +0100106// char *buf = NULL, *out = NULL;
107// size_t buf_len = 0, out_len = 0;
108// int dynamic;
David Sedláka5004e62018-12-16 23:54:47 +0100109
David Sedlák3017da42019-02-15 09:48:04 +0100110// /* check if belongs-to has argument module */
111// ret = lyxml_get_attribute(xml_ctx, data, &prefix_out, &prefix_len, &name, &name_len);
112// LY_CHECK_RET1(ret);
113// if (match_argument_name(name, name_len) != YIN_ARG_MODULE) {
114// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"module\".", name);
115// return LY_EINVAL;
116// }
David Sedláka5004e62018-12-16 23:54:47 +0100117
David Sedlák3017da42019-02-15 09:48:04 +0100118// /* read content of argument */
119// ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
120// LY_CHECK_RET1(ret);
121// *belongsto = lydict_insert(xml_ctx->ctx, out, out_len);
122// LY_CHECK_ERR_RET(!belongsto, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedláka5004e62018-12-16 23:54:47 +0100123
David Sedlák3017da42019-02-15 09:48:04 +0100124// /* read substatements */
125// while (xml_ctx->status == LYXML_ATTRIBUTE) {
126// ret = lyxml_get_attribute(xml_ctx, data, &prefix_out, &prefix_len, &name, &name_len);
127// LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), ret);
128// kw = match_keyword(name);
David Sedláka5004e62018-12-16 23:54:47 +0100129
David Sedlák3017da42019-02-15 09:48:04 +0100130// switch (kw) {
131// case YANG_PREFIX:
132// ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
133// *prefix = lydict_insert(xml_ctx->ctx, out, out_len);
134// break;
135// case YANG_CUSTOM:
136// /* TODO parse extension */
137// break;
138// default:
139// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected attribute");
140// return LY_EVALID;
141// }
142// }
David Sedláka5004e62018-12-16 23:54:47 +0100143
David Sedlák3017da42019-02-15 09:48:04 +0100144// if (!prefix) {
145// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Missing prefix");
146// return LY_EVALID;
147// }
David Sedlákc10e7902018-12-17 02:17:59 +0100148
David Sedlák3017da42019-02-15 09:48:04 +0100149// return LY_SUCCESS;
150// }
David Sedláka5004e62018-12-16 23:54:47 +0100151
152LY_ERR
David Sedlák4a4c0722018-11-26 17:03:10 +0100153parse_namespace(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod_p)
154{
155 LY_ERR ret = LY_SUCCESS;
156 const char *prefix, *name;
157 size_t prefix_len, name_len;
158
159 char *buf = NULL, *out = NULL;
160 size_t buf_len = 0, out_len = 0;
161 int dynamic;
162
David Sedlák4a4c0722018-11-26 17:03:10 +0100163 /* check if namespace has argument uri */
164 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákc10e7902018-12-17 02:17:59 +0100165 LY_CHECK_RET1(ret);
David Sedlák4a4c0722018-11-26 17:03:10 +0100166 if (match_argument_name(name, name_len) != YIN_ARG_URI) {
David Sedlákc10e7902018-12-17 02:17:59 +0100167 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"uri\".", name);
168 return LY_EVALID;
David Sedlák4a4c0722018-11-26 17:03:10 +0100169 }
170
David Sedlákc10e7902018-12-17 02:17:59 +0100171 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
172 LY_CHECK_RET1(ret);
David Sedlák3017da42019-02-15 09:48:04 +0100173 (*mod_p)->mod->ns = lydict_insert(xml_ctx->ctx, out, out_len);
174 LY_CHECK_ERR_RET(!(*mod_p)->mod->ns, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák4a4c0722018-11-26 17:03:10 +0100175
David Sedlákc10e7902018-12-17 02:17:59 +0100176 /* namespace can only have one argument */
David Sedlák4a4c0722018-11-26 17:03:10 +0100177 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákc10e7902018-12-17 02:17:59 +0100178 LY_CHECK_RET1(ret);
179 if (name) {
180 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected argument \"%s\".", name);
181 return LY_EVALID;
182 }
David Sedlák4a4c0722018-11-26 17:03:10 +0100183
184 return LY_SUCCESS;
185}
186
187LY_ERR
188parse_prefix(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod_p)
189{
190 LY_ERR ret = LY_SUCCESS;
191 const char *prefix, *name;
192 size_t prefix_len, name_len;
193
194 char *buf = NULL, *out = NULL;
195 size_t buf_len = 0, out_len = 0;
196 int dynamic;
197
David Sedlákc10e7902018-12-17 02:17:59 +0100198 /* check if prefix has argument value */
David Sedlák4a4c0722018-11-26 17:03:10 +0100199 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákc10e7902018-12-17 02:17:59 +0100200 LY_CHECK_RET1(ret);
David Sedlák4a4c0722018-11-26 17:03:10 +0100201 if (match_argument_name(name, name_len) != YIN_ARG_VALUE) {
David Sedlákc10e7902018-12-17 02:17:59 +0100202 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"value\".", name);
203 return LY_EVALID;
David Sedlák4a4c0722018-11-26 17:03:10 +0100204 }
205
David Sedlákc10e7902018-12-17 02:17:59 +0100206 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
207 LY_CHECK_RET1(ret);
David Sedlák3017da42019-02-15 09:48:04 +0100208 (*mod_p)->mod->prefix = lydict_insert(xml_ctx->ctx, out, out_len);
209 LY_CHECK_ERR_RET(!(*mod_p)->mod->prefix, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák4a4c0722018-11-26 17:03:10 +0100210
David Sedlák3017da42019-02-15 09:48:04 +0100211 /* prefix element can have only one argument */
David Sedlák4a4c0722018-11-26 17:03:10 +0100212 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákc10e7902018-12-17 02:17:59 +0100213 LY_CHECK_RET1(ret);
214 if (name) {
215 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected argument \"%s\".", name);
216 return LY_EVALID;
217 }
David Sedlák4a4c0722018-11-26 17:03:10 +0100218 return LY_SUCCESS;
219}
220
221LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100222parse_mod(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200223{
David Sedlákf3b24f62018-11-02 10:40:47 +0100224 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100225 enum yang_keyword kw = YANG_NONE;
David Sedláke4889912018-11-02 09:52:40 +0100226 const char *prefix, *name;
David Sedlák3b4db242018-10-19 16:11:01 +0200227 size_t prefix_len, name_len;
228
David Sedlákf3b24f62018-11-02 10:40:47 +0100229 char *buf = NULL, *out = NULL;
230 size_t buf_len = 0, out_len = 0;
231 int dynamic;
232
David Sedlák3017da42019-02-15 09:48:04 +0100233 /* check if module has argument "name" */
David Sedlák3b4db242018-10-19 16:11:01 +0200234 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
235 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák872c7b42018-10-26 13:15:20 +0200236 if (match_argument_name(name, name_len) != YIN_ARG_NAME) {
David Sedlákc10e7902018-12-17 02:17:59 +0100237 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"name\".", name);
David Sedlák3b4db242018-10-19 16:11:01 +0200238 }
239
David Sedlákf3b24f62018-11-02 10:40:47 +0100240 /* read module name */
David Sedlák4a4c0722018-11-26 17:03:10 +0100241 if (xml_ctx->status != LYXML_ATTR_CONTENT) {
David Sedlákc10e7902018-12-17 02:17:59 +0100242 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Missing value of argument \"name\"");
David Sedlák4a4c0722018-11-26 17:03:10 +0100243 }
David Sedlák3b4db242018-10-19 16:11:01 +0200244 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
245 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák3017da42019-02-15 09:48:04 +0100246 (*mod)->mod->name = lydict_insert(xml_ctx->ctx, out, out_len);
247 LY_CHECK_ERR_RET(!(*mod)->mod->name, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlákf3b24f62018-11-02 10:40:47 +0100248
David Sedlákc10e7902018-12-17 02:17:59 +0100249 /* read all attributes and their content only for testing */
David Sedlák4a4c0722018-11-26 17:03:10 +0100250 while (xml_ctx->status == LYXML_ATTRIBUTE) {
251 lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákc10e7902018-12-17 02:17:59 +0100252 while (xml_ctx->status == LYXML_ATTR_CONTENT) {
253 lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák4a4c0722018-11-26 17:03:10 +0100254 }
255 }
256
257 while (xml_ctx->status == LYXML_ELEMENT || xml_ctx->status == LYXML_ELEM_CONTENT) {
258 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák4a4c0722018-11-26 17:03:10 +0100259 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
260 kw = match_keyword(name);
261
262 switch (kw) {
David Sedlák4a4c0722018-11-26 17:03:10 +0100263 case YANG_NAMESPACE:
David Sedlák3017da42019-02-15 09:48:04 +0100264 ret = parse_namespace(xml_ctx, data, mod);
David Sedlák4a4c0722018-11-26 17:03:10 +0100265 break;
David Sedláka5004e62018-12-16 23:54:47 +0100266 case YANG_PREFIX:
David Sedlák3017da42019-02-15 09:48:04 +0100267 ret = parse_prefix(xml_ctx, data, mod);
David Sedlákc10e7902018-12-17 02:17:59 +0100268 /* TODO change lysp_check_prefix function to work with ctx and not parser_ctx */
269 //LY_CHECK_RET(lysp_check_prefix(&xml_ctx->ctx, *mod_p, &((*mod_p)->prefix)), LY_EVALID);
David Sedláka5004e62018-12-16 23:54:47 +0100270 break;
David Sedlák4a4c0722018-11-26 17:03:10 +0100271
272 default:
David Sedláka5004e62018-12-16 23:54:47 +0100273 /* error */
David Sedlák4a4c0722018-11-26 17:03:10 +0100274 break;
275 }
276 }
277
David Sedlákf3b24f62018-11-02 10:40:47 +0100278 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200279}
280
David Sedlák3017da42019-02-15 09:48:04 +0100281// LY_ERR
282// yin_parse_submodule(struct ly_ctx *ctx, const char *data, struct lysp_submodule **submod)
283// {
284// LY_ERR ret = LY_SUCCESS;
285// enum yang_keyword kw = YANG_NONE;
286// struct lyxml_context xml_ctx;
287// struct lysp_submodule *mod_p = NULL;
288// const char *prefix, *name;
289// size_t prefix_len, name_len;
290
291// /* initialize xml context */
292// memset(&xml_ctx, 0, sizeof xml_ctx);
293// xml_ctx.ctx = ctx;
294// xml_ctx.line = 1;
295
296// /* check submodule */
297// ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
298// LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
299// kw = match_keyword(name);
300// if (kw == YANG_MODULE) {
301// LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
302// ret = LY_EINVAL;
303// goto cleanup;
304// } else if (kw != YANG_SUBMODULE) {
305// /* TODO log error using LOGVAL_YIN macro */
306// ret = LY_EVALID;
307// goto cleanup;
308// }
309
310// /* allocate module */
311// mod_p = calloc(1, sizeof *mod_p);
312// LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
313// mod_p->parsing = 1;
314
315// /* parser submodule substatements */
316// ret = parse_submodule(&xml_ctx, &data, mod_p);
317// LY_CHECK_GOTO(ret, cleanup);
318
319// mod_p->parsing = 0;
320// *submod = mod_p;
321
322// cleanup:
323// if (ret) {
324// lysp_submodule_free(ctx, mod_p);
325// }
326
327// lyxml_context_clear(&xml_ctx);
328// return ret;
329// }
330
David Sedlák3b4db242018-10-19 16:11:01 +0200331LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100332yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200333{
David Sedláke4889912018-11-02 09:52:40 +0100334 LY_ERR ret = LY_SUCCESS;
335 enum yang_keyword kw = YANG_NONE;
David Sedlák3b4db242018-10-19 16:11:01 +0200336 struct lyxml_context xml_ctx;
David Sedlák3017da42019-02-15 09:48:04 +0100337 struct lysp_module *mod_p = NULL;
338 const char *prefix, *name;
339 size_t prefix_len, name_len;
David Sedlák3b4db242018-10-19 16:11:01 +0200340
David Sedlák3017da42019-02-15 09:48:04 +0100341 /* initialize xml context */
David Sedláke4889912018-11-02 09:52:40 +0100342 memset(&xml_ctx, 0, sizeof xml_ctx);
343 xml_ctx.ctx = ctx;
344 xml_ctx.line = 1;
345
David Sedlák3017da42019-02-15 09:48:04 +0100346 /* check submodule */
David Sedláke4889912018-11-02 09:52:40 +0100347 ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák3017da42019-02-15 09:48:04 +0100348 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedláke4889912018-11-02 09:52:40 +0100349 kw = match_keyword(name);
David Sedláke4889912018-11-02 09:52:40 +0100350 if (kw == YANG_SUBMODULE) {
David Sedlák3017da42019-02-15 09:48:04 +0100351 LOGERR(ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
352 ret = LY_EINVAL;
353 goto cleanup;
354 } else if (kw != YANG_MODULE) {
355 /* TODO log error using LOGVAL_YIN macro */
356 ret = LY_EVALID;
357 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +0100358 }
359
David Sedlák3017da42019-02-15 09:48:04 +0100360 /* allocate module */
361 mod_p = calloc(1, sizeof *mod_p);
362 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
363 mod_p->mod = mod;
364 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +0100365
David Sedlák3017da42019-02-15 09:48:04 +0100366 /* parser module substatements */
367 ret = parse_mod(&xml_ctx, &data, &mod_p);
368 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +0100369
David Sedlák3017da42019-02-15 09:48:04 +0100370 mod_p->parsing = 0;
371 mod->parsed = mod_p;
372
373cleanup:
374 if (ret) {
375 lysp_module_free(mod_p);
376 }
377
David Sedlák2e411422018-12-17 02:35:39 +0100378 lyxml_context_clear(&xml_ctx);
379 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200380}