blob: 4bd1ab387a99f9440e3672ac1d14978ee5ae0186 [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ákd5318ee2019-02-15 10:14:50 +010038/**
39 * @brief Match argument name.
40 *
41 * @param[in] name String representing name.
42 * @param[in] len Lenght of the name.
43 *
44 * @reurn YIN_ARGUMENT value.
45 */
David Sedlák872c7b42018-10-26 13:15:20 +020046enum YIN_ARGUMENT
David Sedláke4889912018-11-02 09:52:40 +010047match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020048{
David Sedlák872c7b42018-10-26 13:15:20 +020049 enum YIN_ARGUMENT arg = YIN_ARG_NONE;
50 size_t already_read = 0;
David Sedlák3b4db242018-10-19 16:11:01 +020051
David Sedlák94de2aa2019-02-15 12:42:11 +010052#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
53#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +010054#define IF_ARG_PREFIX_END }
55
David Sedlák872c7b42018-10-26 13:15:20 +020056 switch(*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +010057 case 'c':
58 already_read += 1;
59 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +020060 break;
David Sedlák872c7b42018-10-26 13:15:20 +020061
David Sedlák94de2aa2019-02-15 12:42:11 +010062 case 'd':
63 already_read += 1;
64 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +020065 break;
David Sedlák872c7b42018-10-26 13:15:20 +020066
David Sedlák94de2aa2019-02-15 12:42:11 +010067 case 'm':
68 already_read += 1;
69 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +020070 break;
71
David Sedlák94de2aa2019-02-15 12:42:11 +010072 case 'n':
73 already_read += 1;
74 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +020075 break;
76
David Sedlák94de2aa2019-02-15 12:42:11 +010077 case 't':
78 already_read += 1;
79 IF_ARG_PREFIX("a", 1)
80 IF_ARG("g", 1, YIN_ARG_TAG)
81 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
82 IF_ARG_PREFIX_END
83 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +020084 break;
David Sedlák872c7b42018-10-26 13:15:20 +020085
David Sedlák94de2aa2019-02-15 12:42:11 +010086 case 'u':
87 already_read += 1;
88 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +020089 break;
David Sedlák872c7b42018-10-26 13:15:20 +020090
David Sedlák94de2aa2019-02-15 12:42:11 +010091 case 'v':
92 already_read += 1;
93 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +020094 break;
95 }
96
David Sedlákc10e7902018-12-17 02:17:59 +010097 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +020098 if (already_read != len) {
99 arg = YIN_ARG_NONE;
100 }
101
102 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200103}
104
David Sedlák3017da42019-02-15 09:48:04 +0100105// LY_ERR
106// parser_belongs_to(struct lyxml_context *xml_ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext **extensions)
107// {
108// enum yang_keyword kw = YANG_NONE;
109// LY_ERR ret = LY_SUCCESS;
110// const char *prefix_out, *name;
111// size_t prefix_len, name_len;
David Sedláka5004e62018-12-16 23:54:47 +0100112
David Sedlák3017da42019-02-15 09:48:04 +0100113// char *buf = NULL, *out = NULL;
114// size_t buf_len = 0, out_len = 0;
115// int dynamic;
David Sedláka5004e62018-12-16 23:54:47 +0100116
David Sedlák3017da42019-02-15 09:48:04 +0100117// /* check if belongs-to has argument module */
118// ret = lyxml_get_attribute(xml_ctx, data, &prefix_out, &prefix_len, &name, &name_len);
119// LY_CHECK_RET1(ret);
120// if (match_argument_name(name, name_len) != YIN_ARG_MODULE) {
121// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"module\".", name);
122// return LY_EINVAL;
123// }
David Sedláka5004e62018-12-16 23:54:47 +0100124
David Sedlák3017da42019-02-15 09:48:04 +0100125// /* read content of argument */
126// ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
127// LY_CHECK_RET1(ret);
128// *belongsto = lydict_insert(xml_ctx->ctx, out, out_len);
129// LY_CHECK_ERR_RET(!belongsto, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedláka5004e62018-12-16 23:54:47 +0100130
David Sedlák3017da42019-02-15 09:48:04 +0100131// /* read substatements */
132// while (xml_ctx->status == LYXML_ATTRIBUTE) {
133// ret = lyxml_get_attribute(xml_ctx, data, &prefix_out, &prefix_len, &name, &name_len);
134// LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), ret);
135// kw = match_keyword(name);
David Sedláka5004e62018-12-16 23:54:47 +0100136
David Sedlák3017da42019-02-15 09:48:04 +0100137// switch (kw) {
138// case YANG_PREFIX:
139// ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
140// *prefix = lydict_insert(xml_ctx->ctx, out, out_len);
141// break;
142// case YANG_CUSTOM:
143// /* TODO parse extension */
144// break;
145// default:
146// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected attribute");
147// return LY_EVALID;
148// }
149// }
David Sedláka5004e62018-12-16 23:54:47 +0100150
David Sedlák3017da42019-02-15 09:48:04 +0100151// if (!prefix) {
152// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Missing prefix");
153// return LY_EVALID;
154// }
David Sedlákc10e7902018-12-17 02:17:59 +0100155
David Sedlák3017da42019-02-15 09:48:04 +0100156// return LY_SUCCESS;
157// }
David Sedláka5004e62018-12-16 23:54:47 +0100158
David Sedlákd5318ee2019-02-15 10:14:50 +0100159/**
160 * @brief Parse namespace statement.
161 *
162 * @param[in] xml_ctx xml context.
163 * @param[in, out] data Data to read from.
164 * @param[in, out] mod_p Module to write to.
165 *
166 * @return LY_ERR values.
167 */
David Sedláka5004e62018-12-16 23:54:47 +0100168LY_ERR
David Sedlák4a4c0722018-11-26 17:03:10 +0100169parse_namespace(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod_p)
170{
171 LY_ERR ret = LY_SUCCESS;
172 const char *prefix, *name;
173 size_t prefix_len, name_len;
174
175 char *buf = NULL, *out = NULL;
176 size_t buf_len = 0, out_len = 0;
177 int dynamic;
178
David Sedlák4a4c0722018-11-26 17:03:10 +0100179 /* check if namespace has argument uri */
180 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák94de2aa2019-02-15 12:42:11 +0100181 LY_CHECK_RET(ret);
David Sedlák4a4c0722018-11-26 17:03:10 +0100182 if (match_argument_name(name, name_len) != YIN_ARG_URI) {
David Sedlákc10e7902018-12-17 02:17:59 +0100183 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"uri\".", name);
184 return LY_EVALID;
David Sedlák4a4c0722018-11-26 17:03:10 +0100185 }
186
David Sedlákc10e7902018-12-17 02:17:59 +0100187 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák94de2aa2019-02-15 12:42:11 +0100188 LY_CHECK_RET(ret);
David Sedlák3017da42019-02-15 09:48:04 +0100189 (*mod_p)->mod->ns = lydict_insert(xml_ctx->ctx, out, out_len);
190 LY_CHECK_ERR_RET(!(*mod_p)->mod->ns, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák4a4c0722018-11-26 17:03:10 +0100191
David Sedlákd5318ee2019-02-15 10:14:50 +0100192 /* namespace can have only one argument */
David Sedlák4a4c0722018-11-26 17:03:10 +0100193 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák94de2aa2019-02-15 12:42:11 +0100194 LY_CHECK_RET(ret);
David Sedlákc10e7902018-12-17 02:17:59 +0100195 if (name) {
196 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected argument \"%s\".", name);
197 return LY_EVALID;
198 }
David Sedlák4a4c0722018-11-26 17:03:10 +0100199
200 return LY_SUCCESS;
201}
202
David Sedlákd5318ee2019-02-15 10:14:50 +0100203/**
204 * @brief Parse prefix statement.
205 *
206 * @param[in] xml_ctx Xml context.
207 * @param[in, out] data Data to reda from.
208 * @param[out] mod_p Module to write to.
209 *
210 * @return LY_ERR values.
211 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100212LY_ERR
213parse_prefix(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod_p)
214{
215 LY_ERR ret = LY_SUCCESS;
216 const char *prefix, *name;
217 size_t prefix_len, name_len;
218
219 char *buf = NULL, *out = NULL;
220 size_t buf_len = 0, out_len = 0;
221 int dynamic;
222
David Sedlákc10e7902018-12-17 02:17:59 +0100223 /* check if prefix has argument value */
David Sedlák4a4c0722018-11-26 17:03:10 +0100224 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák94de2aa2019-02-15 12:42:11 +0100225 LY_CHECK_RET(ret);
David Sedlák4a4c0722018-11-26 17:03:10 +0100226 if (match_argument_name(name, name_len) != YIN_ARG_VALUE) {
David Sedlákc10e7902018-12-17 02:17:59 +0100227 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"value\".", name);
228 return LY_EVALID;
David Sedlák4a4c0722018-11-26 17:03:10 +0100229 }
230
David Sedlákc10e7902018-12-17 02:17:59 +0100231 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák94de2aa2019-02-15 12:42:11 +0100232 LY_CHECK_RET(ret);
David Sedlák3017da42019-02-15 09:48:04 +0100233 (*mod_p)->mod->prefix = lydict_insert(xml_ctx->ctx, out, out_len);
234 LY_CHECK_ERR_RET(!(*mod_p)->mod->prefix, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák4a4c0722018-11-26 17:03:10 +0100235
David Sedlák3017da42019-02-15 09:48:04 +0100236 /* prefix element can have only one argument */
David Sedlák4a4c0722018-11-26 17:03:10 +0100237 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák94de2aa2019-02-15 12:42:11 +0100238 LY_CHECK_RET(ret);
David Sedlákc10e7902018-12-17 02:17:59 +0100239 if (name) {
240 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected argument \"%s\".", name);
241 return LY_EVALID;
242 }
David Sedlák4a4c0722018-11-26 17:03:10 +0100243 return LY_SUCCESS;
244}
245
David Sedlákd5318ee2019-02-15 10:14:50 +0100246/**
247 * @brief Parse module substatements.
248 *
249 * @param[in] xml_ctx xml context.
250 * @param[in, out] data Data to read from.
251 * @param[out] mod Parsed module structure
252 *
253 * @return LY_ERR values.
254 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100255LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100256parse_mod(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200257{
David Sedlákf3b24f62018-11-02 10:40:47 +0100258 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100259 enum yang_keyword kw = YANG_NONE;
David Sedláke4889912018-11-02 09:52:40 +0100260 const char *prefix, *name;
David Sedlák3b4db242018-10-19 16:11:01 +0200261 size_t prefix_len, name_len;
David Sedlák4b4713f2019-02-15 13:47:45 +0100262 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
David Sedlák3b4db242018-10-19 16:11:01 +0200263
David Sedlákf3b24f62018-11-02 10:40:47 +0100264 char *buf = NULL, *out = NULL;
265 size_t buf_len = 0, out_len = 0;
266 int dynamic;
267
David Sedlák3017da42019-02-15 09:48:04 +0100268 /* check if module has argument "name" */
David Sedlák3b4db242018-10-19 16:11:01 +0200269 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
270 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák872c7b42018-10-26 13:15:20 +0200271 if (match_argument_name(name, name_len) != YIN_ARG_NAME) {
David Sedlákc10e7902018-12-17 02:17:59 +0100272 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 +0200273 }
274
David Sedlákf3b24f62018-11-02 10:40:47 +0100275 /* read module name */
David Sedlák4a4c0722018-11-26 17:03:10 +0100276 if (xml_ctx->status != LYXML_ATTR_CONTENT) {
David Sedlákc10e7902018-12-17 02:17:59 +0100277 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 +0100278 }
David Sedlák3b4db242018-10-19 16:11:01 +0200279 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
280 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák3017da42019-02-15 09:48:04 +0100281 (*mod)->mod->name = lydict_insert(xml_ctx->ctx, out, out_len);
282 LY_CHECK_ERR_RET(!(*mod)->mod->name, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlákf3b24f62018-11-02 10:40:47 +0100283
David Sedlákc10e7902018-12-17 02:17:59 +0100284 /* read all attributes and their content only for testing */
David Sedlák4a4c0722018-11-26 17:03:10 +0100285 while (xml_ctx->status == LYXML_ATTRIBUTE) {
286 lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákc10e7902018-12-17 02:17:59 +0100287 while (xml_ctx->status == LYXML_ATTR_CONTENT) {
288 lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák4a4c0722018-11-26 17:03:10 +0100289 }
290 }
291
292 while (xml_ctx->status == LYXML_ELEMENT || xml_ctx->status == LYXML_ELEM_CONTENT) {
David Sedlák4b4713f2019-02-15 13:47:45 +0100293
294/* TODO ADD error log to macro */
295#define CHECK_ORDER(SECTION) \
296 if (mod_stmt > SECTION) {return LY_EVALID;}mod_stmt = SECTION
297
298 switch (kw) {
299 /* module header */
300 case YANG_NAMESPACE:
301 case YANG_PREFIX:
302 CHECK_ORDER(Y_MOD_MODULE_HEADER);
303 break;
304 case YANG_YANG_VERSION:
305 CHECK_ORDER(Y_MOD_MODULE_HEADER);
306 break;
307 /* linkage */
308 case YANG_INCLUDE:
309 case YANG_IMPORT:
310 CHECK_ORDER(Y_MOD_LINKAGE);
311 break;
312 /* meta */
313 case YANG_ORGANIZATION:
314 case YANG_CONTACT:
315 case YANG_DESCRIPTION:
316 case YANG_REFERENCE:
317 CHECK_ORDER(Y_MOD_META);
318 break;
319
320 /* revision */
321 case YANG_REVISION:
322 CHECK_ORDER(Y_MOD_REVISION);
323 break;
324 /* body */
325 case YANG_ANYDATA:
326 case YANG_ANYXML:
327 case YANG_AUGMENT:
328 case YANG_CHOICE:
329 case YANG_CONTAINER:
330 case YANG_DEVIATION:
331 case YANG_EXTENSION:
332 case YANG_FEATURE:
333 case YANG_GROUPING:
334 case YANG_IDENTITY:
335 case YANG_LEAF:
336 case YANG_LEAF_LIST:
337 case YANG_LIST:
338 case YANG_NOTIFICATION:
339 case YANG_RPC:
340 case YANG_TYPEDEF:
341 case YANG_USES:
342 case YANG_CUSTOM:
343 mod_stmt = Y_MOD_BODY;
344 break;
345 default:
346 /* error will be handled in the next switch */
347 break;
348 }
349#undef CHECK_ORDER
350
David Sedlák4a4c0722018-11-26 17:03:10 +0100351 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák4a4c0722018-11-26 17:03:10 +0100352 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák94de2aa2019-02-15 12:42:11 +0100353 kw = match_keyword(name, name_len);
David Sedlák4a4c0722018-11-26 17:03:10 +0100354
355 switch (kw) {
David Sedlák4a4c0722018-11-26 17:03:10 +0100356 case YANG_NAMESPACE:
David Sedlák3017da42019-02-15 09:48:04 +0100357 ret = parse_namespace(xml_ctx, data, mod);
David Sedlák4a4c0722018-11-26 17:03:10 +0100358 break;
David Sedláka5004e62018-12-16 23:54:47 +0100359 case YANG_PREFIX:
David Sedlák3017da42019-02-15 09:48:04 +0100360 ret = parse_prefix(xml_ctx, data, mod);
David Sedlákc10e7902018-12-17 02:17:59 +0100361 /* TODO change lysp_check_prefix function to work with ctx and not parser_ctx */
362 //LY_CHECK_RET(lysp_check_prefix(&xml_ctx->ctx, *mod_p, &((*mod_p)->prefix)), LY_EVALID);
David Sedláka5004e62018-12-16 23:54:47 +0100363 break;
David Sedlák4a4c0722018-11-26 17:03:10 +0100364
365 default:
David Sedláka5004e62018-12-16 23:54:47 +0100366 /* error */
David Sedlák4a4c0722018-11-26 17:03:10 +0100367 break;
368 }
369 }
370
David Sedlákf3b24f62018-11-02 10:40:47 +0100371 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200372}
373
David Sedlákd5318ee2019-02-15 10:14:50 +0100374/**
375 * @brief Parse yin submodule.
376 *
377 * @param[in] ctx Context of YANG schemas.
378 * @param[in] data Data to read from.
379 * @param[out] submod Module to write to.
380 *
381 * @return LY_ERR values.
382 */
383LY_ERR
384yin_parse_submodule(struct ly_ctx *ctx, const char *data, struct lysp_submodule **submod)
385{
386 LY_ERR ret = LY_SUCCESS;
387 enum yang_keyword kw = YANG_NONE;
388 struct lyxml_context xml_ctx;
389 struct lysp_submodule *mod_p = NULL;
390 const char *prefix, *name;
391 size_t prefix_len, name_len;
David Sedlák3017da42019-02-15 09:48:04 +0100392
David Sedlákd5318ee2019-02-15 10:14:50 +0100393 /* initialize xml context */
394 memset(&xml_ctx, 0, sizeof xml_ctx);
395 xml_ctx.ctx = ctx;
396 xml_ctx.line = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100397
David Sedlákd5318ee2019-02-15 10:14:50 +0100398 /* check submodule */
399 ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
400 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák94de2aa2019-02-15 12:42:11 +0100401 kw = match_keyword(name, name_len);
David Sedlákd5318ee2019-02-15 10:14:50 +0100402 if (kw == YANG_MODULE) {
403 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
404 ret = LY_EINVAL;
405 goto cleanup;
406 } else if (kw != YANG_SUBMODULE) {
407 /* TODO log error using LOGVAL_YIN macro */
408 ret = LY_EVALID;
409 goto cleanup;
410 }
David Sedlák3017da42019-02-15 09:48:04 +0100411
David Sedlákd5318ee2019-02-15 10:14:50 +0100412 /* allocate module */
413 mod_p = calloc(1, sizeof *mod_p);
414 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
415 mod_p->parsing = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100416
David Sedlákd5318ee2019-02-15 10:14:50 +0100417 /* parser submodule substatements */
418 //ret = parse_submod(&xml_ctx, &data, mod_p);
419 LY_CHECK_GOTO(ret, cleanup);
David Sedlák3017da42019-02-15 09:48:04 +0100420
David Sedlákd5318ee2019-02-15 10:14:50 +0100421 mod_p->parsing = 0;
422 *submod = mod_p;
David Sedlák3017da42019-02-15 09:48:04 +0100423
David Sedlákd5318ee2019-02-15 10:14:50 +0100424cleanup:
425 if (ret) {
426 lysp_submodule_free(ctx, mod_p);
427 }
David Sedlák3017da42019-02-15 09:48:04 +0100428
David Sedlákd5318ee2019-02-15 10:14:50 +0100429 lyxml_context_clear(&xml_ctx);
430 return ret;
431}
David Sedlák3017da42019-02-15 09:48:04 +0100432
David Sedlákd5318ee2019-02-15 10:14:50 +0100433/**
434 * @brief Parse yin module.
435 *
436 * @param[in] ctx Context of YANG schemas.
437 * @param[in] data Data to read from.
438 * @param[out] mod Module to write to.
439 *
440 * @return LY_ERR values.
441 */
David Sedlák3b4db242018-10-19 16:11:01 +0200442LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100443yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200444{
David Sedláke4889912018-11-02 09:52:40 +0100445 LY_ERR ret = LY_SUCCESS;
446 enum yang_keyword kw = YANG_NONE;
David Sedlák3b4db242018-10-19 16:11:01 +0200447 struct lyxml_context xml_ctx;
David Sedlák3017da42019-02-15 09:48:04 +0100448 struct lysp_module *mod_p = NULL;
449 const char *prefix, *name;
450 size_t prefix_len, name_len;
David Sedlák3b4db242018-10-19 16:11:01 +0200451
David Sedlák3017da42019-02-15 09:48:04 +0100452 /* initialize xml context */
David Sedláke4889912018-11-02 09:52:40 +0100453 memset(&xml_ctx, 0, sizeof xml_ctx);
454 xml_ctx.ctx = ctx;
455 xml_ctx.line = 1;
456
David Sedlák3017da42019-02-15 09:48:04 +0100457 /* check submodule */
David Sedláke4889912018-11-02 09:52:40 +0100458 ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák3017da42019-02-15 09:48:04 +0100459 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák94de2aa2019-02-15 12:42:11 +0100460 kw = match_keyword(name, name_len);
David Sedláke4889912018-11-02 09:52:40 +0100461 if (kw == YANG_SUBMODULE) {
David Sedlák3017da42019-02-15 09:48:04 +0100462 LOGERR(ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
463 ret = LY_EINVAL;
464 goto cleanup;
465 } else if (kw != YANG_MODULE) {
466 /* TODO log error using LOGVAL_YIN macro */
467 ret = LY_EVALID;
468 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +0100469 }
470
David Sedlák3017da42019-02-15 09:48:04 +0100471 /* allocate module */
472 mod_p = calloc(1, sizeof *mod_p);
473 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
474 mod_p->mod = mod;
475 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +0100476
David Sedlák3017da42019-02-15 09:48:04 +0100477 /* parser module substatements */
478 ret = parse_mod(&xml_ctx, &data, &mod_p);
479 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +0100480
David Sedlák3017da42019-02-15 09:48:04 +0100481 mod_p->parsing = 0;
482 mod->parsed = mod_p;
483
484cleanup:
485 if (ret) {
486 lysp_module_free(mod_p);
487 }
488
David Sedlák2e411422018-12-17 02:35:39 +0100489 lyxml_context_clear(&xml_ctx);
490 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200491}