blob: aa67056bda74d805cf3d143dc96142a3015d2a06 [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ák1c8b2702019-02-22 11:03:02 +010038LY_ERR
39parse_text_element(struct lyxml_context *xml_ctx, const char **data, const char **value)
40{
41 LY_ERR ret = LY_SUCCESS;
42 char *buf = NULL, *out = NULL;
43 size_t buf_len = 0, out_len = 0;
44 int dynamic;
45
46 const char *prefix, *name;
47 size_t prefix_len, name_len;
48
49
50 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
51 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
52 LY_CHECK_RET(ret);
53 *value = lydict_insert(xml_ctx->ctx, out, out_len);
54 LY_CHECK_ERR_RET(!(*value), LOGMEM(xml_ctx->ctx), LY_EMEM);
55 }
56
57 LY_CHECK_ERR_RET(xml_ctx->status != LYXML_ELEMENT, "erere", LY_EINT);
58 lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
59
60 return 0;
61}
62
David Sedlákd5318ee2019-02-15 10:14:50 +010063/**
64 * @brief Match argument name.
65 *
66 * @param[in] name String representing name.
67 * @param[in] len Lenght of the name.
68 *
69 * @reurn YIN_ARGUMENT value.
70 */
David Sedlák872c7b42018-10-26 13:15:20 +020071enum YIN_ARGUMENT
David Sedláke4889912018-11-02 09:52:40 +010072match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020073{
David Sedlák872c7b42018-10-26 13:15:20 +020074 enum YIN_ARGUMENT arg = YIN_ARG_NONE;
75 size_t already_read = 0;
David Sedlák3b4db242018-10-19 16:11:01 +020076
David Sedlák94de2aa2019-02-15 12:42:11 +010077#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
78#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +010079#define IF_ARG_PREFIX_END }
80
David Sedlák1c8b2702019-02-22 11:03:02 +010081 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +010082 case 'c':
83 already_read += 1;
84 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +020085 break;
David Sedlák872c7b42018-10-26 13:15:20 +020086
David Sedlák94de2aa2019-02-15 12:42:11 +010087 case 'd':
88 already_read += 1;
89 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +020090 break;
David Sedlák872c7b42018-10-26 13:15:20 +020091
David Sedlák94de2aa2019-02-15 12:42:11 +010092 case 'm':
93 already_read += 1;
94 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +020095 break;
96
David Sedlák94de2aa2019-02-15 12:42:11 +010097 case 'n':
98 already_read += 1;
99 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200100 break;
101
David Sedlák94de2aa2019-02-15 12:42:11 +0100102 case 't':
103 already_read += 1;
104 IF_ARG_PREFIX("a", 1)
105 IF_ARG("g", 1, YIN_ARG_TAG)
106 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
107 IF_ARG_PREFIX_END
108 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200109 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200110
David Sedlák94de2aa2019-02-15 12:42:11 +0100111 case 'u':
112 already_read += 1;
113 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200114 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200115
David Sedlák94de2aa2019-02-15 12:42:11 +0100116 case 'v':
117 already_read += 1;
118 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200119 break;
120 }
121
David Sedlákc10e7902018-12-17 02:17:59 +0100122 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200123 if (already_read != len) {
124 arg = YIN_ARG_NONE;
125 }
126
127 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200128}
129
David Sedlák3017da42019-02-15 09:48:04 +0100130// LY_ERR
131// parser_belongs_to(struct lyxml_context *xml_ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext **extensions)
132// {
133// enum yang_keyword kw = YANG_NONE;
134// LY_ERR ret = LY_SUCCESS;
135// const char *prefix_out, *name;
136// size_t prefix_len, name_len;
David Sedláka5004e62018-12-16 23:54:47 +0100137
David Sedlák3017da42019-02-15 09:48:04 +0100138// char *buf = NULL, *out = NULL;
139// size_t buf_len = 0, out_len = 0;
140// int dynamic;
David Sedláka5004e62018-12-16 23:54:47 +0100141
David Sedlák3017da42019-02-15 09:48:04 +0100142// /* check if belongs-to has argument module */
143// ret = lyxml_get_attribute(xml_ctx, data, &prefix_out, &prefix_len, &name, &name_len);
144// LY_CHECK_RET1(ret);
145// if (match_argument_name(name, name_len) != YIN_ARG_MODULE) {
146// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"module\".", name);
147// return LY_EINVAL;
148// }
David Sedláka5004e62018-12-16 23:54:47 +0100149
David Sedlák3017da42019-02-15 09:48:04 +0100150// /* read content of argument */
151// ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
152// LY_CHECK_RET1(ret);
153// *belongsto = lydict_insert(xml_ctx->ctx, out, out_len);
154// LY_CHECK_ERR_RET(!belongsto, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedláka5004e62018-12-16 23:54:47 +0100155
David Sedlák3017da42019-02-15 09:48:04 +0100156// /* read substatements */
157// while (xml_ctx->status == LYXML_ATTRIBUTE) {
158// ret = lyxml_get_attribute(xml_ctx, data, &prefix_out, &prefix_len, &name, &name_len);
159// LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), ret);
160// kw = match_keyword(name);
David Sedláka5004e62018-12-16 23:54:47 +0100161
David Sedlák3017da42019-02-15 09:48:04 +0100162// switch (kw) {
163// case YANG_PREFIX:
164// ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
165// *prefix = lydict_insert(xml_ctx->ctx, out, out_len);
166// break;
167// case YANG_CUSTOM:
168// /* TODO parse extension */
169// break;
170// default:
171// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected attribute");
172// return LY_EVALID;
173// }
174// }
David Sedláka5004e62018-12-16 23:54:47 +0100175
David Sedlák3017da42019-02-15 09:48:04 +0100176// if (!prefix) {
177// LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Missing prefix");
178// return LY_EVALID;
179// }
David Sedlákc10e7902018-12-17 02:17:59 +0100180
David Sedlák3017da42019-02-15 09:48:04 +0100181// return LY_SUCCESS;
182// }
David Sedláka5004e62018-12-16 23:54:47 +0100183
David Sedlákd5318ee2019-02-15 10:14:50 +0100184/**
185 * @brief Parse namespace statement.
186 *
187 * @param[in] xml_ctx xml context.
188 * @param[in, out] data Data to read from.
189 * @param[in, out] mod_p Module to write to.
190 *
191 * @return LY_ERR values.
192 */
David Sedláka5004e62018-12-16 23:54:47 +0100193LY_ERR
David Sedlák4a4c0722018-11-26 17:03:10 +0100194parse_namespace(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod_p)
195{
196 LY_ERR ret = LY_SUCCESS;
197 const char *prefix, *name;
198 size_t prefix_len, name_len;
199
200 char *buf = NULL, *out = NULL;
201 size_t buf_len = 0, out_len = 0;
202 int dynamic;
203
David Sedlák4a4c0722018-11-26 17:03:10 +0100204 /* check if namespace has argument uri */
205 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák94de2aa2019-02-15 12:42:11 +0100206 LY_CHECK_RET(ret);
David Sedlák4a4c0722018-11-26 17:03:10 +0100207 if (match_argument_name(name, name_len) != YIN_ARG_URI) {
David Sedlákc10e7902018-12-17 02:17:59 +0100208 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"uri\".", name);
209 return LY_EVALID;
David Sedlák4a4c0722018-11-26 17:03:10 +0100210 }
211
David Sedlákc10e7902018-12-17 02:17:59 +0100212 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák94de2aa2019-02-15 12:42:11 +0100213 LY_CHECK_RET(ret);
David Sedlák3017da42019-02-15 09:48:04 +0100214 (*mod_p)->mod->ns = lydict_insert(xml_ctx->ctx, out, out_len);
215 LY_CHECK_ERR_RET(!(*mod_p)->mod->ns, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák4a4c0722018-11-26 17:03:10 +0100216
David Sedlákd5318ee2019-02-15 10:14:50 +0100217 /* namespace can have only one argument */
David Sedlák4a4c0722018-11-26 17:03:10 +0100218 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák94de2aa2019-02-15 12:42:11 +0100219 LY_CHECK_RET(ret);
David Sedlákc10e7902018-12-17 02:17:59 +0100220 if (name) {
221 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected argument \"%s\".", name);
222 return LY_EVALID;
223 }
David Sedlák4a4c0722018-11-26 17:03:10 +0100224
225 return LY_SUCCESS;
226}
227
David Sedlákd5318ee2019-02-15 10:14:50 +0100228/**
229 * @brief Parse prefix statement.
230 *
231 * @param[in] xml_ctx Xml context.
232 * @param[in, out] data Data to reda from.
233 * @param[out] mod_p Module to write to.
234 *
235 * @return LY_ERR values.
236 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100237LY_ERR
238parse_prefix(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod_p)
239{
240 LY_ERR ret = LY_SUCCESS;
241 const char *prefix, *name;
242 size_t prefix_len, name_len;
243
244 char *buf = NULL, *out = NULL;
245 size_t buf_len = 0, out_len = 0;
246 int dynamic;
247
David Sedlákc10e7902018-12-17 02:17:59 +0100248 /* check if prefix has argument value */
David Sedlák4a4c0722018-11-26 17:03:10 +0100249 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák94de2aa2019-02-15 12:42:11 +0100250 LY_CHECK_RET(ret);
David Sedlák4a4c0722018-11-26 17:03:10 +0100251 if (match_argument_name(name, name_len) != YIN_ARG_VALUE) {
David Sedlákc10e7902018-12-17 02:17:59 +0100252 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"value\".", name);
253 return LY_EVALID;
David Sedlák4a4c0722018-11-26 17:03:10 +0100254 }
255
David Sedlákc10e7902018-12-17 02:17:59 +0100256 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák94de2aa2019-02-15 12:42:11 +0100257 LY_CHECK_RET(ret);
David Sedlák3017da42019-02-15 09:48:04 +0100258 (*mod_p)->mod->prefix = lydict_insert(xml_ctx->ctx, out, out_len);
259 LY_CHECK_ERR_RET(!(*mod_p)->mod->prefix, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák4a4c0722018-11-26 17:03:10 +0100260
David Sedlák3017da42019-02-15 09:48:04 +0100261 /* prefix element can have only one argument */
David Sedlák4a4c0722018-11-26 17:03:10 +0100262 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák94de2aa2019-02-15 12:42:11 +0100263 LY_CHECK_RET(ret);
David Sedlákc10e7902018-12-17 02:17:59 +0100264 if (name) {
265 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Unexpected argument \"%s\".", name);
266 return LY_EVALID;
267 }
David Sedlák4a4c0722018-11-26 17:03:10 +0100268 return LY_SUCCESS;
269}
270
David Sedlák736fd0d2019-02-15 16:06:31 +0100271static LY_ERR
272yin_parse_import(struct lyxml_context *xml_ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
273{
274 LY_ERR ret = LY_SUCCESS;
275 enum yang_keyword kw;
276 struct lysp_import *imp;
277 const char *prefix, *name;
278 size_t prefix_len, name_len;
279
280 char *buf = NULL, *out = NULL;
281 size_t buf_len = 0, out_len = 0;
282 int dynamic;
283
284 /* allocate sized array for imports */
285 LY_ARRAY_NEW_RET(xml_ctx->ctx, *imports, imp, LY_EVALID);
286
287 /* get value */
288 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
289 LY_CHECK_RET(ret);
290 if (match_argument_name(name, name_len) != YIN_ARG_MODULE) {
David Sedlák1c8b2702019-02-22 11:03:02 +0100291 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 +0100292 return LY_EVALID;
293 }
294 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
295 LY_CHECK_RET(ret);
296 imp->name = lydict_insert(xml_ctx->ctx, out, out_len);
297 LY_CHECK_ERR_RET(!imp->name, LOGMEM(xml_ctx->ctx), LY_EMEM);
298
299
300 while ((ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len) == LY_SUCCESS && name != NULL)) {
301 kw = match_keyword(name, name_len);
302 switch (kw) {
303 case YANG_PREFIX:
304 /* TODO parse prefix */
305 case YANG_DESCRIPTION:
306 /* TODO parse description */
307 case YANG_REFERENCE:
308 /* TODO parse reference */
309 case YANG_REVISION_DATE:
310 /* TODO parse revision date */
311 case YANG_CUSTOM:
312 /* TODO parse extension */
313 default:
314 /* TODO log error */
315 return LY_EVALID;
316 }
317 }
318
319 /* TODO add log macro and log error */
320 LY_CHECK_RET(!imp->prefix);
321 return ret;
322}
323
David Sedlákd5318ee2019-02-15 10:14:50 +0100324/**
325 * @brief Parse module substatements.
326 *
327 * @param[in] xml_ctx xml context.
328 * @param[in, out] data Data to read from.
329 * @param[out] mod Parsed module structure
330 *
331 * @return LY_ERR values.
332 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100333LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100334parse_mod(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200335{
David Sedlákf3b24f62018-11-02 10:40:47 +0100336 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100337 enum yang_keyword kw = YANG_NONE;
David Sedláke4889912018-11-02 09:52:40 +0100338 const char *prefix, *name;
David Sedlák3b4db242018-10-19 16:11:01 +0200339 size_t prefix_len, name_len;
David Sedlák4b4713f2019-02-15 13:47:45 +0100340 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
David Sedlák3b4db242018-10-19 16:11:01 +0200341
David Sedlákf3b24f62018-11-02 10:40:47 +0100342 char *buf = NULL, *out = NULL;
343 size_t buf_len = 0, out_len = 0;
344 int dynamic;
345
David Sedlák3017da42019-02-15 09:48:04 +0100346 /* check if module has argument "name" */
David Sedlák3b4db242018-10-19 16:11:01 +0200347 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
348 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák872c7b42018-10-26 13:15:20 +0200349 if (match_argument_name(name, name_len) != YIN_ARG_NAME) {
David Sedlákc10e7902018-12-17 02:17:59 +0100350 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 +0200351 }
352
David Sedlákf3b24f62018-11-02 10:40:47 +0100353 /* read module name */
David Sedlák4a4c0722018-11-26 17:03:10 +0100354 if (xml_ctx->status != LYXML_ATTR_CONTENT) {
David Sedlákc10e7902018-12-17 02:17:59 +0100355 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 +0100356 }
David Sedlák3b4db242018-10-19 16:11:01 +0200357 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
358 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák3017da42019-02-15 09:48:04 +0100359 (*mod)->mod->name = lydict_insert(xml_ctx->ctx, out, out_len);
360 LY_CHECK_ERR_RET(!(*mod)->mod->name, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlákf3b24f62018-11-02 10:40:47 +0100361
David Sedlákc10e7902018-12-17 02:17:59 +0100362 /* read all attributes and their content only for testing */
David Sedlák4a4c0722018-11-26 17:03:10 +0100363 while (xml_ctx->status == LYXML_ATTRIBUTE) {
364 lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákc10e7902018-12-17 02:17:59 +0100365 while (xml_ctx->status == LYXML_ATTR_CONTENT) {
366 lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák4a4c0722018-11-26 17:03:10 +0100367 }
368 }
369
David Sedlák736fd0d2019-02-15 16:06:31 +0100370 /* loop over all elements and parse them */
David Sedlák4a4c0722018-11-26 17:03:10 +0100371 while (xml_ctx->status == LYXML_ELEMENT || xml_ctx->status == LYXML_ELEM_CONTENT) {
David Sedlák4b4713f2019-02-15 13:47:45 +0100372
373/* TODO ADD error log to macro */
374#define CHECK_ORDER(SECTION) \
375 if (mod_stmt > SECTION) {return LY_EVALID;}mod_stmt = SECTION
376
377 switch (kw) {
378 /* module header */
379 case YANG_NAMESPACE:
380 case YANG_PREFIX:
381 CHECK_ORDER(Y_MOD_MODULE_HEADER);
382 break;
383 case YANG_YANG_VERSION:
384 CHECK_ORDER(Y_MOD_MODULE_HEADER);
385 break;
386 /* linkage */
387 case YANG_INCLUDE:
388 case YANG_IMPORT:
389 CHECK_ORDER(Y_MOD_LINKAGE);
390 break;
391 /* meta */
392 case YANG_ORGANIZATION:
393 case YANG_CONTACT:
394 case YANG_DESCRIPTION:
395 case YANG_REFERENCE:
396 CHECK_ORDER(Y_MOD_META);
397 break;
398
399 /* revision */
400 case YANG_REVISION:
401 CHECK_ORDER(Y_MOD_REVISION);
402 break;
403 /* body */
404 case YANG_ANYDATA:
405 case YANG_ANYXML:
406 case YANG_AUGMENT:
407 case YANG_CHOICE:
408 case YANG_CONTAINER:
409 case YANG_DEVIATION:
410 case YANG_EXTENSION:
411 case YANG_FEATURE:
412 case YANG_GROUPING:
413 case YANG_IDENTITY:
414 case YANG_LEAF:
415 case YANG_LEAF_LIST:
416 case YANG_LIST:
417 case YANG_NOTIFICATION:
418 case YANG_RPC:
419 case YANG_TYPEDEF:
420 case YANG_USES:
421 case YANG_CUSTOM:
422 mod_stmt = Y_MOD_BODY;
423 break;
424 default:
425 /* error will be handled in the next switch */
426 break;
427 }
428#undef CHECK_ORDER
429
David Sedlák4a4c0722018-11-26 17:03:10 +0100430 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák4a4c0722018-11-26 17:03:10 +0100431 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák94de2aa2019-02-15 12:42:11 +0100432 kw = match_keyword(name, name_len);
David Sedlák4a4c0722018-11-26 17:03:10 +0100433
434 switch (kw) {
David Sedlák736fd0d2019-02-15 16:06:31 +0100435
436 /* module header */
437 case YANG_NAMESPACE:
438 LY_CHECK_RET(parse_namespace(xml_ctx, data, mod));
David Sedlák4a4c0722018-11-26 17:03:10 +0100439 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100440 case YANG_PREFIX:
441 LY_CHECK_RET(parse_prefix(xml_ctx, data, mod));
442 /* TODO change lysp_check_prefix function to work with ctx and not parser_ctx */
443 //LY_CHECK_RET(lysp_check_prefix(&xml_ctx->ctx, *mod_p, &((*mod_p)->prefix)), LY_EVALID);
David Sedláka5004e62018-12-16 23:54:47 +0100444 break;
David Sedlák4a4c0722018-11-26 17:03:10 +0100445
David Sedlák736fd0d2019-02-15 16:06:31 +0100446 /* linkage */
447 case YANG_IMPORT:
448 yin_parse_import(xml_ctx, (*mod)->mod->prefix, data, &(*mod)->imports);
David Sedlák1c8b2702019-02-22 11:03:02 +0100449 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100450
David Sedlák1c8b2702019-02-22 11:03:02 +0100451 /* meta */
452 case YANG_ORGANIZATION:
453 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->org));
454 break;
455 case YANG_CONTACT:
456 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->contact));
457 break;
458 case YANG_DESCRIPTION:
459 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->dsc));
460 break;
461 case YANG_REFERENCE:
462 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->ref));
463 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100464
465 default:
466 /* error */
David Sedlák4a4c0722018-11-26 17:03:10 +0100467 break;
468 }
469 }
470
David Sedlákf3b24f62018-11-02 10:40:47 +0100471 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200472}
473
David Sedlákd5318ee2019-02-15 10:14:50 +0100474/**
475 * @brief Parse yin submodule.
476 *
477 * @param[in] ctx Context of YANG schemas.
478 * @param[in] data Data to read from.
479 * @param[out] submod Module to write to.
480 *
481 * @return LY_ERR values.
482 */
483LY_ERR
484yin_parse_submodule(struct ly_ctx *ctx, const char *data, struct lysp_submodule **submod)
485{
486 LY_ERR ret = LY_SUCCESS;
487 enum yang_keyword kw = YANG_NONE;
488 struct lyxml_context xml_ctx;
489 struct lysp_submodule *mod_p = NULL;
490 const char *prefix, *name;
491 size_t prefix_len, name_len;
David Sedlák3017da42019-02-15 09:48:04 +0100492
David Sedlákd5318ee2019-02-15 10:14:50 +0100493 /* initialize xml context */
494 memset(&xml_ctx, 0, sizeof xml_ctx);
495 xml_ctx.ctx = ctx;
496 xml_ctx.line = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100497
David Sedlákd5318ee2019-02-15 10:14:50 +0100498 /* check submodule */
499 ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
500 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák94de2aa2019-02-15 12:42:11 +0100501 kw = match_keyword(name, name_len);
David Sedlákd5318ee2019-02-15 10:14:50 +0100502 if (kw == YANG_MODULE) {
503 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
504 ret = LY_EINVAL;
505 goto cleanup;
506 } else if (kw != YANG_SUBMODULE) {
507 /* TODO log error using LOGVAL_YIN macro */
508 ret = LY_EVALID;
509 goto cleanup;
510 }
David Sedlák3017da42019-02-15 09:48:04 +0100511
David Sedlákd5318ee2019-02-15 10:14:50 +0100512 /* allocate module */
513 mod_p = calloc(1, sizeof *mod_p);
514 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
515 mod_p->parsing = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100516
David Sedlákd5318ee2019-02-15 10:14:50 +0100517 /* parser submodule substatements */
518 //ret = parse_submod(&xml_ctx, &data, mod_p);
519 LY_CHECK_GOTO(ret, cleanup);
David Sedlák3017da42019-02-15 09:48:04 +0100520
David Sedlákd5318ee2019-02-15 10:14:50 +0100521 mod_p->parsing = 0;
522 *submod = mod_p;
David Sedlák3017da42019-02-15 09:48:04 +0100523
David Sedlákd5318ee2019-02-15 10:14:50 +0100524cleanup:
525 if (ret) {
526 lysp_submodule_free(ctx, mod_p);
527 }
David Sedlák3017da42019-02-15 09:48:04 +0100528
David Sedlákd5318ee2019-02-15 10:14:50 +0100529 lyxml_context_clear(&xml_ctx);
530 return ret;
531}
David Sedlák3017da42019-02-15 09:48:04 +0100532
David Sedlákd5318ee2019-02-15 10:14:50 +0100533/**
534 * @brief Parse yin module.
535 *
536 * @param[in] ctx Context of YANG schemas.
537 * @param[in] data Data to read from.
538 * @param[out] mod Module to write to.
539 *
540 * @return LY_ERR values.
541 */
David Sedlák3b4db242018-10-19 16:11:01 +0200542LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100543yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200544{
David Sedláke4889912018-11-02 09:52:40 +0100545 LY_ERR ret = LY_SUCCESS;
546 enum yang_keyword kw = YANG_NONE;
David Sedlák3b4db242018-10-19 16:11:01 +0200547 struct lyxml_context xml_ctx;
David Sedlák3017da42019-02-15 09:48:04 +0100548 struct lysp_module *mod_p = NULL;
549 const char *prefix, *name;
550 size_t prefix_len, name_len;
David Sedlák3b4db242018-10-19 16:11:01 +0200551
David Sedlák3017da42019-02-15 09:48:04 +0100552 /* initialize xml context */
David Sedláke4889912018-11-02 09:52:40 +0100553 memset(&xml_ctx, 0, sizeof xml_ctx);
554 xml_ctx.ctx = ctx;
555 xml_ctx.line = 1;
556
David Sedlák3017da42019-02-15 09:48:04 +0100557 /* check submodule */
David Sedláke4889912018-11-02 09:52:40 +0100558 ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák3017da42019-02-15 09:48:04 +0100559 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák94de2aa2019-02-15 12:42:11 +0100560 kw = match_keyword(name, name_len);
David Sedláke4889912018-11-02 09:52:40 +0100561 if (kw == YANG_SUBMODULE) {
David Sedlák3017da42019-02-15 09:48:04 +0100562 LOGERR(ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
563 ret = LY_EINVAL;
564 goto cleanup;
565 } else if (kw != YANG_MODULE) {
566 /* TODO log error using LOGVAL_YIN macro */
567 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}