blob: ab137239a7e47caa9ece91f8a102c2eeb171226a [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ákc136b972019-03-08 13:39:06 +010038/**
39 * @brief Parse content of whole element as text.
40 *
41 * @param[in] xml_ctx Xml context.
42 * @param[in] data Data to read from.
43 * @param[out] value Where content of element should be stored.
44 */
David Sedlák1c8b2702019-02-22 11:03:02 +010045LY_ERR
46parse_text_element(struct lyxml_context *xml_ctx, const char **data, const char **value)
47{
48 LY_ERR ret = LY_SUCCESS;
49 char *buf = NULL, *out = NULL;
50 size_t buf_len = 0, out_len = 0;
51 int dynamic;
52
53 const char *prefix, *name;
54 size_t prefix_len, name_len;
55
56
57 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
58 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
59 LY_CHECK_RET(ret);
60 *value = lydict_insert(xml_ctx->ctx, out, out_len);
61 LY_CHECK_ERR_RET(!(*value), LOGMEM(xml_ctx->ctx), LY_EMEM);
62 }
63
David Sedlák1c8b2702019-02-22 11:03:02 +010064 lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
65
66 return 0;
67}
68
David Sedlákd5318ee2019-02-15 10:14:50 +010069/**
70 * @brief Match argument name.
71 *
72 * @param[in] name String representing name.
73 * @param[in] len Lenght of the name.
74 *
75 * @reurn YIN_ARGUMENT value.
76 */
David Sedlák872c7b42018-10-26 13:15:20 +020077enum YIN_ARGUMENT
David Sedláke4889912018-11-02 09:52:40 +010078match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020079{
David Sedlák872c7b42018-10-26 13:15:20 +020080 enum YIN_ARGUMENT arg = YIN_ARG_NONE;
81 size_t already_read = 0;
David Sedlák3b4db242018-10-19 16:11:01 +020082
David Sedlák94de2aa2019-02-15 12:42:11 +010083#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
84#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +010085#define IF_ARG_PREFIX_END }
86
David Sedlák1c8b2702019-02-22 11:03:02 +010087 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +010088 case 'c':
89 already_read += 1;
90 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +020091 break;
David Sedlák872c7b42018-10-26 13:15:20 +020092
David Sedlák94de2aa2019-02-15 12:42:11 +010093 case 'd':
94 already_read += 1;
95 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +020096 break;
David Sedlák872c7b42018-10-26 13:15:20 +020097
David Sedlák94de2aa2019-02-15 12:42:11 +010098 case 'm':
99 already_read += 1;
100 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200101 break;
102
David Sedlák94de2aa2019-02-15 12:42:11 +0100103 case 'n':
104 already_read += 1;
105 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200106 break;
107
David Sedlák94de2aa2019-02-15 12:42:11 +0100108 case 't':
109 already_read += 1;
110 IF_ARG_PREFIX("a", 1)
111 IF_ARG("g", 1, YIN_ARG_TAG)
112 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
113 IF_ARG_PREFIX_END
114 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200115 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200116
David Sedlák94de2aa2019-02-15 12:42:11 +0100117 case 'u':
118 already_read += 1;
119 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200120 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200121
David Sedlák94de2aa2019-02-15 12:42:11 +0100122 case 'v':
123 already_read += 1;
124 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200125 break;
126 }
127
David Sedlákc10e7902018-12-17 02:17:59 +0100128 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200129 if (already_read != len) {
130 arg = YIN_ARG_NONE;
131 }
132
133 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200134}
135
David Sedlák3017da42019-02-15 09:48:04 +0100136// LY_ERR
137// parser_belongs_to(struct lyxml_context *xml_ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext **extensions)
138// {
139// enum yang_keyword kw = YANG_NONE;
140// LY_ERR ret = LY_SUCCESS;
141// const char *prefix_out, *name;
142// size_t prefix_len, name_len;
David Sedláka5004e62018-12-16 23:54:47 +0100143
David Sedlák3017da42019-02-15 09:48:04 +0100144// char *buf = NULL, *out = NULL;
145// size_t buf_len = 0, out_len = 0;
146// int dynamic;
David Sedláka5004e62018-12-16 23:54:47 +0100147
David Sedlák3017da42019-02-15 09:48:04 +0100148// /* check if belongs-to has argument module */
149// ret = lyxml_get_attribute(xml_ctx, data, &prefix_out, &prefix_len, &name, &name_len);
150// LY_CHECK_RET1(ret);
151// if (match_argument_name(name, name_len) != YIN_ARG_MODULE) {
152// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"module\".", name);
153// return LY_EINVAL;
154// }
David Sedláka5004e62018-12-16 23:54:47 +0100155
David Sedlák3017da42019-02-15 09:48:04 +0100156// /* read content of argument */
157// ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
158// LY_CHECK_RET1(ret);
159// *belongsto = lydict_insert(xml_ctx->ctx, out, out_len);
160// LY_CHECK_ERR_RET(!belongsto, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedláka5004e62018-12-16 23:54:47 +0100161
David Sedlák3017da42019-02-15 09:48:04 +0100162// /* read substatements */
163// while (xml_ctx->status == LYXML_ATTRIBUTE) {
164// ret = lyxml_get_attribute(xml_ctx, data, &prefix_out, &prefix_len, &name, &name_len);
165// LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), ret);
166// kw = match_keyword(name);
David Sedláka5004e62018-12-16 23:54:47 +0100167
David Sedlák3017da42019-02-15 09:48:04 +0100168// switch (kw) {
169// case YANG_PREFIX:
170// ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
171// *prefix = lydict_insert(xml_ctx->ctx, out, out_len);
172// break;
173// case YANG_CUSTOM:
174// /* TODO parse extension */
175// break;
176// default:
177// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected attribute");
178// return LY_EVALID;
179// }
180// }
David Sedláka5004e62018-12-16 23:54:47 +0100181
David Sedlák3017da42019-02-15 09:48:04 +0100182// if (!prefix) {
183// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Missing prefix");
184// return LY_EVALID;
185// }
David Sedlákc10e7902018-12-17 02:17:59 +0100186
David Sedlák3017da42019-02-15 09:48:04 +0100187// return LY_SUCCESS;
188// }
David Sedláka5004e62018-12-16 23:54:47 +0100189
David Sedlákd5318ee2019-02-15 10:14:50 +0100190/**
191 * @brief Parse namespace statement.
192 *
193 * @param[in] xml_ctx xml context.
194 * @param[in, out] data Data to read from.
195 * @param[in, out] mod_p Module to write to.
196 *
197 * @return LY_ERR values.
198 */
David Sedláka5004e62018-12-16 23:54:47 +0100199LY_ERR
David Sedlák4a4c0722018-11-26 17:03:10 +0100200parse_namespace(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod_p)
201{
202 LY_ERR ret = LY_SUCCESS;
203 const char *prefix, *name;
204 size_t prefix_len, name_len;
205
206 char *buf = NULL, *out = NULL;
207 size_t buf_len = 0, out_len = 0;
208 int dynamic;
209
David Sedlák4a4c0722018-11-26 17:03:10 +0100210 /* check if namespace has argument uri */
211 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák94de2aa2019-02-15 12:42:11 +0100212 LY_CHECK_RET(ret);
David Sedlák4a4c0722018-11-26 17:03:10 +0100213 if (match_argument_name(name, name_len) != YIN_ARG_URI) {
David Sedlákc10e7902018-12-17 02:17:59 +0100214 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"uri\".", name);
215 return LY_EVALID;
David Sedlák4a4c0722018-11-26 17:03:10 +0100216 }
217
David Sedlákc10e7902018-12-17 02:17:59 +0100218 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák94de2aa2019-02-15 12:42:11 +0100219 LY_CHECK_RET(ret);
David Sedlák3017da42019-02-15 09:48:04 +0100220 (*mod_p)->mod->ns = lydict_insert(xml_ctx->ctx, out, out_len);
221 LY_CHECK_ERR_RET(!(*mod_p)->mod->ns, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák4a4c0722018-11-26 17:03:10 +0100222
David Sedlákd5318ee2019-02-15 10:14:50 +0100223 /* namespace can have only one argument */
David Sedlákc136b972019-03-08 13:39:06 +0100224 if (xml_ctx->status != LYXML_ELEMENT) {
David Sedlákc10e7902018-12-17 02:17:59 +0100225 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected argument \"%s\".", name);
226 return LY_EVALID;
227 }
David Sedlák4a4c0722018-11-26 17:03:10 +0100228
229 return LY_SUCCESS;
230}
231
David Sedlákd5318ee2019-02-15 10:14:50 +0100232/**
233 * @brief Parse prefix statement.
234 *
235 * @param[in] xml_ctx Xml context.
236 * @param[in, out] data Data to reda from.
237 * @param[out] mod_p Module to write to.
238 *
239 * @return LY_ERR values.
240 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100241LY_ERR
242parse_prefix(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod_p)
243{
244 LY_ERR ret = LY_SUCCESS;
245 const char *prefix, *name;
246 size_t prefix_len, name_len;
247
248 char *buf = NULL, *out = NULL;
249 size_t buf_len = 0, out_len = 0;
250 int dynamic;
251
David Sedlákc10e7902018-12-17 02:17:59 +0100252 /* check if prefix has argument value */
David Sedlák4a4c0722018-11-26 17:03:10 +0100253 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák94de2aa2019-02-15 12:42:11 +0100254 LY_CHECK_RET(ret);
David Sedlák4a4c0722018-11-26 17:03:10 +0100255 if (match_argument_name(name, name_len) != YIN_ARG_VALUE) {
David Sedlákc10e7902018-12-17 02:17:59 +0100256 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"value\".", name);
257 return LY_EVALID;
David Sedlák4a4c0722018-11-26 17:03:10 +0100258 }
259
David Sedlákc10e7902018-12-17 02:17:59 +0100260 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák94de2aa2019-02-15 12:42:11 +0100261 LY_CHECK_RET(ret);
David Sedlák3017da42019-02-15 09:48:04 +0100262 (*mod_p)->mod->prefix = lydict_insert(xml_ctx->ctx, out, out_len);
263 LY_CHECK_ERR_RET(!(*mod_p)->mod->prefix, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák4a4c0722018-11-26 17:03:10 +0100264
David Sedlák3017da42019-02-15 09:48:04 +0100265 /* prefix element can have only one argument */
David Sedlákc136b972019-03-08 13:39:06 +0100266 if (xml_ctx->status != LYXML_ELEMENT) {
David Sedlákc10e7902018-12-17 02:17:59 +0100267 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected argument \"%s\".", name);
268 return LY_EVALID;
269 }
David Sedlák4a4c0722018-11-26 17:03:10 +0100270 return LY_SUCCESS;
271}
272
David Sedlák736fd0d2019-02-15 16:06:31 +0100273static LY_ERR
274yin_parse_import(struct lyxml_context *xml_ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
275{
276 LY_ERR ret = LY_SUCCESS;
277 enum yang_keyword kw;
278 struct lysp_import *imp;
279 const char *prefix, *name;
280 size_t prefix_len, name_len;
281
282 char *buf = NULL, *out = NULL;
283 size_t buf_len = 0, out_len = 0;
284 int dynamic;
285
286 /* allocate sized array for imports */
287 LY_ARRAY_NEW_RET(xml_ctx->ctx, *imports, imp, LY_EVALID);
288
289 /* get value */
290 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
291 LY_CHECK_RET(ret);
292 if (match_argument_name(name, name_len) != YIN_ARG_MODULE) {
David Sedlák1c8b2702019-02-22 11:03:02 +0100293 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"module\".", name);
David Sedlák736fd0d2019-02-15 16:06:31 +0100294 return LY_EVALID;
295 }
296 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
297 LY_CHECK_RET(ret);
298 imp->name = lydict_insert(xml_ctx->ctx, out, out_len);
299 LY_CHECK_ERR_RET(!imp->name, LOGMEM(xml_ctx->ctx), LY_EMEM);
300
301
302 while ((ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len) == LY_SUCCESS && name != NULL)) {
303 kw = match_keyword(name, name_len);
304 switch (kw) {
305 case YANG_PREFIX:
306 /* TODO parse prefix */
307 case YANG_DESCRIPTION:
308 /* TODO parse description */
309 case YANG_REFERENCE:
310 /* TODO parse reference */
311 case YANG_REVISION_DATE:
312 /* TODO parse revision date */
313 case YANG_CUSTOM:
314 /* TODO parse extension */
315 default:
316 /* TODO log error */
317 return LY_EVALID;
318 }
319 }
320
321 /* TODO add log macro and log error */
322 LY_CHECK_RET(!imp->prefix);
323 return ret;
324}
325
David Sedlákd5318ee2019-02-15 10:14:50 +0100326/**
327 * @brief Parse module substatements.
328 *
329 * @param[in] xml_ctx xml context.
330 * @param[in, out] data Data to read from.
331 * @param[out] mod Parsed module structure
332 *
333 * @return LY_ERR values.
334 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100335LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100336parse_mod(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200337{
David Sedlákf3b24f62018-11-02 10:40:47 +0100338 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100339 enum yang_keyword kw = YANG_NONE;
David Sedláke4889912018-11-02 09:52:40 +0100340 const char *prefix, *name;
David Sedlák3b4db242018-10-19 16:11:01 +0200341 size_t prefix_len, name_len;
David Sedlák4b4713f2019-02-15 13:47:45 +0100342 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
David Sedlák3b4db242018-10-19 16:11:01 +0200343
David Sedlákf3b24f62018-11-02 10:40:47 +0100344 char *buf = NULL, *out = NULL;
345 size_t buf_len = 0, out_len = 0;
346 int dynamic;
347
David Sedlák3017da42019-02-15 09:48:04 +0100348 /* check if module has argument "name" */
David Sedlák3b4db242018-10-19 16:11:01 +0200349 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
350 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák872c7b42018-10-26 13:15:20 +0200351 if (match_argument_name(name, name_len) != YIN_ARG_NAME) {
David Sedlákc10e7902018-12-17 02:17:59 +0100352 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 +0200353 }
354
David Sedlákf3b24f62018-11-02 10:40:47 +0100355 /* read module name */
David Sedlák4a4c0722018-11-26 17:03:10 +0100356 if (xml_ctx->status != LYXML_ATTR_CONTENT) {
David Sedlákc10e7902018-12-17 02:17:59 +0100357 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 +0100358 }
David Sedlák3b4db242018-10-19 16:11:01 +0200359 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
360 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák3017da42019-02-15 09:48:04 +0100361 (*mod)->mod->name = lydict_insert(xml_ctx->ctx, out, out_len);
362 LY_CHECK_ERR_RET(!(*mod)->mod->name, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlákf3b24f62018-11-02 10:40:47 +0100363
David Sedlákc136b972019-03-08 13:39:06 +0100364 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
365 LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_YANG(xml_ctx, LYVE_SYNTAX_YIN, "Expected new xml element after module element"), LY_EINVAL);
David Sedlák4a4c0722018-11-26 17:03:10 +0100366
David Sedlák736fd0d2019-02-15 16:06:31 +0100367 /* loop over all elements and parse them */
David Sedlákc136b972019-03-08 13:39:06 +0100368 while (xml_ctx->status != LYXML_END) {
David Sedlák4b4713f2019-02-15 13:47:45 +0100369/* TODO ADD error log to macro */
370#define CHECK_ORDER(SECTION) \
371 if (mod_stmt > SECTION) {return LY_EVALID;}mod_stmt = SECTION
372
373 switch (kw) {
374 /* module header */
375 case YANG_NAMESPACE:
376 case YANG_PREFIX:
377 CHECK_ORDER(Y_MOD_MODULE_HEADER);
378 break;
379 case YANG_YANG_VERSION:
380 CHECK_ORDER(Y_MOD_MODULE_HEADER);
381 break;
382 /* linkage */
383 case YANG_INCLUDE:
384 case YANG_IMPORT:
385 CHECK_ORDER(Y_MOD_LINKAGE);
386 break;
387 /* meta */
388 case YANG_ORGANIZATION:
389 case YANG_CONTACT:
390 case YANG_DESCRIPTION:
391 case YANG_REFERENCE:
392 CHECK_ORDER(Y_MOD_META);
393 break;
394
395 /* revision */
396 case YANG_REVISION:
397 CHECK_ORDER(Y_MOD_REVISION);
398 break;
399 /* body */
400 case YANG_ANYDATA:
401 case YANG_ANYXML:
402 case YANG_AUGMENT:
403 case YANG_CHOICE:
404 case YANG_CONTAINER:
405 case YANG_DEVIATION:
406 case YANG_EXTENSION:
407 case YANG_FEATURE:
408 case YANG_GROUPING:
409 case YANG_IDENTITY:
410 case YANG_LEAF:
411 case YANG_LEAF_LIST:
412 case YANG_LIST:
413 case YANG_NOTIFICATION:
414 case YANG_RPC:
415 case YANG_TYPEDEF:
416 case YANG_USES:
417 case YANG_CUSTOM:
418 mod_stmt = Y_MOD_BODY;
419 break;
420 default:
421 /* error will be handled in the next switch */
422 break;
423 }
424#undef CHECK_ORDER
425
David Sedlák4a4c0722018-11-26 17:03:10 +0100426 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákc136b972019-03-08 13:39:06 +0100427 LY_CHECK_RET(ret != LY_SUCCESS, LY_EMEM);
David Sedlák4a4c0722018-11-26 17:03:10 +0100428
David Sedlákc136b972019-03-08 13:39:06 +0100429 if (name) {
430 kw = match_keyword(name, name_len);
431 switch (kw) {
David Sedlák736fd0d2019-02-15 16:06:31 +0100432
David Sedlákc136b972019-03-08 13:39:06 +0100433 /* module header */
434 case YANG_NAMESPACE:
435 LY_CHECK_RET(parse_namespace(xml_ctx, data, mod));
436 break;
437 case YANG_PREFIX:
438 LY_CHECK_RET(parse_prefix(xml_ctx, data, mod));
439 /* TODO change lysp_check_prefix function to work with ctx and not parser_ctx */
440 //LY_CHECK_RET(lysp_check_prefix(&xml_ctx->ctx, *mod_p, &((*mod_p)->prefix)), LY_EVALID);
441 break;
David Sedlák4a4c0722018-11-26 17:03:10 +0100442
David Sedlákc136b972019-03-08 13:39:06 +0100443 /* linkage */
444 case YANG_IMPORT:
445 yin_parse_import(xml_ctx, (*mod)->mod->prefix, data, &(*mod)->imports);
446 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100447
David Sedlákc136b972019-03-08 13:39:06 +0100448 /* meta */
449 case YANG_ORGANIZATION:
450 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->org));
451 break;
452 case YANG_CONTACT:
453 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->contact));
454 break;
455 case YANG_DESCRIPTION:
456 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->dsc));
457 break;
458 case YANG_REFERENCE:
459 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->ref));
460 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100461
David Sedlákc136b972019-03-08 13:39:06 +0100462 default:
463 /* error */
464 break;
465 }
David Sedlák4a4c0722018-11-26 17:03:10 +0100466 }
467 }
468
David Sedlákf3b24f62018-11-02 10:40:47 +0100469 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200470}
471
David Sedlákd5318ee2019-02-15 10:14:50 +0100472/**
473 * @brief Parse yin submodule.
474 *
475 * @param[in] ctx Context of YANG schemas.
476 * @param[in] data Data to read from.
477 * @param[out] submod Module to write to.
478 *
479 * @return LY_ERR values.
480 */
481LY_ERR
482yin_parse_submodule(struct ly_ctx *ctx, const char *data, struct lysp_submodule **submod)
483{
484 LY_ERR ret = LY_SUCCESS;
485 enum yang_keyword kw = YANG_NONE;
486 struct lyxml_context xml_ctx;
487 struct lysp_submodule *mod_p = NULL;
488 const char *prefix, *name;
489 size_t prefix_len, name_len;
David Sedlák3017da42019-02-15 09:48:04 +0100490
David Sedlákd5318ee2019-02-15 10:14:50 +0100491 /* initialize xml context */
492 memset(&xml_ctx, 0, sizeof xml_ctx);
493 xml_ctx.ctx = ctx;
494 xml_ctx.line = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100495
David Sedlákd5318ee2019-02-15 10:14:50 +0100496 /* check submodule */
497 ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
498 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák94de2aa2019-02-15 12:42:11 +0100499 kw = match_keyword(name, name_len);
David Sedlákd5318ee2019-02-15 10:14:50 +0100500 if (kw == YANG_MODULE) {
501 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
502 ret = LY_EINVAL;
503 goto cleanup;
504 } else if (kw != YANG_SUBMODULE) {
David Sedlák0a875b42019-03-07 22:24:05 +0100505 LOGVAL_YANG(&xml_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
506 ly_stmt2str(kw));
David Sedlákd5318ee2019-02-15 10:14:50 +0100507 ret = LY_EVALID;
508 goto cleanup;
509 }
David Sedlák3017da42019-02-15 09:48:04 +0100510
David Sedlákd5318ee2019-02-15 10:14:50 +0100511 /* allocate module */
512 mod_p = calloc(1, sizeof *mod_p);
513 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
514 mod_p->parsing = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100515
David Sedlákd5318ee2019-02-15 10:14:50 +0100516 /* parser submodule substatements */
517 //ret = parse_submod(&xml_ctx, &data, mod_p);
518 LY_CHECK_GOTO(ret, cleanup);
David Sedlák3017da42019-02-15 09:48:04 +0100519
David Sedlákd5318ee2019-02-15 10:14:50 +0100520 mod_p->parsing = 0;
521 *submod = mod_p;
David Sedlák3017da42019-02-15 09:48:04 +0100522
David Sedlákd5318ee2019-02-15 10:14:50 +0100523cleanup:
524 if (ret) {
525 lysp_submodule_free(ctx, mod_p);
526 }
David Sedlák3017da42019-02-15 09:48:04 +0100527
David Sedlákd5318ee2019-02-15 10:14:50 +0100528 lyxml_context_clear(&xml_ctx);
529 return ret;
530}
David Sedlák3017da42019-02-15 09:48:04 +0100531
David Sedlákd5318ee2019-02-15 10:14:50 +0100532/**
533 * @brief Parse yin module.
534 *
535 * @param[in] ctx Context of YANG schemas.
536 * @param[in] data Data to read from.
537 * @param[out] mod Module to write to.
538 *
539 * @return LY_ERR values.
540 */
David Sedlák3b4db242018-10-19 16:11:01 +0200541LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100542yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200543{
David Sedláke4889912018-11-02 09:52:40 +0100544 LY_ERR ret = LY_SUCCESS;
545 enum yang_keyword kw = YANG_NONE;
David Sedlák3b4db242018-10-19 16:11:01 +0200546 struct lyxml_context xml_ctx;
David Sedlák3017da42019-02-15 09:48:04 +0100547 struct lysp_module *mod_p = NULL;
548 const char *prefix, *name;
549 size_t prefix_len, name_len;
David Sedlák3b4db242018-10-19 16:11:01 +0200550
David Sedlák3017da42019-02-15 09:48:04 +0100551 /* initialize xml context */
David Sedláke4889912018-11-02 09:52:40 +0100552 memset(&xml_ctx, 0, sizeof xml_ctx);
553 xml_ctx.ctx = ctx;
554 xml_ctx.line = 1;
555
David Sedlák3017da42019-02-15 09:48:04 +0100556 /* check submodule */
David Sedláke4889912018-11-02 09:52:40 +0100557 ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák3017da42019-02-15 09:48:04 +0100558 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák94de2aa2019-02-15 12:42:11 +0100559 kw = match_keyword(name, name_len);
David Sedláke4889912018-11-02 09:52:40 +0100560 if (kw == YANG_SUBMODULE) {
David Sedlák3017da42019-02-15 09:48:04 +0100561 LOGERR(ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
562 ret = LY_EINVAL;
563 goto cleanup;
564 } else if (kw != YANG_MODULE) {
David Sedlák0a875b42019-03-07 22:24:05 +0100565 LOGVAL_YANG(&xml_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
566 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +0100567 ret = LY_EVALID;
568 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +0100569 }
570
David Sedlák3017da42019-02-15 09:48:04 +0100571 /* allocate module */
572 mod_p = calloc(1, sizeof *mod_p);
573 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
574 mod_p->mod = mod;
575 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +0100576
David Sedlák3017da42019-02-15 09:48:04 +0100577 /* parser module substatements */
578 ret = parse_mod(&xml_ctx, &data, &mod_p);
579 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +0100580
David Sedlák3017da42019-02-15 09:48:04 +0100581 mod_p->parsing = 0;
582 mod->parsed = mod_p;
583
584cleanup:
585 if (ret) {
586 lysp_module_free(mod_p);
587 }
588
David Sedlák2e411422018-12-17 02:35:39 +0100589 lyxml_context_clear(&xml_ctx);
590 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200591}