blob: 385d51a814a1bd74ca75f574808f55b2daf9df5a [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ák736fd0d2019-02-15 16:06:31 +0100246static LY_ERR
247yin_parse_import(struct lyxml_context *xml_ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
248{
249 LY_ERR ret = LY_SUCCESS;
250 enum yang_keyword kw;
251 struct lysp_import *imp;
252 const char *prefix, *name;
253 size_t prefix_len, name_len;
254
255 char *buf = NULL, *out = NULL;
256 size_t buf_len = 0, out_len = 0;
257 int dynamic;
258
259 /* allocate sized array for imports */
260 LY_ARRAY_NEW_RET(xml_ctx->ctx, *imports, imp, LY_EVALID);
261
262 /* get value */
263 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
264 LY_CHECK_RET(ret);
265 if (match_argument_name(name, name_len) != YIN_ARG_MODULE) {
266 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"value\".", name);
267 return LY_EVALID;
268 }
269 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
270 LY_CHECK_RET(ret);
271 imp->name = lydict_insert(xml_ctx->ctx, out, out_len);
272 LY_CHECK_ERR_RET(!imp->name, LOGMEM(xml_ctx->ctx), LY_EMEM);
273
274
275 while ((ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len) == LY_SUCCESS && name != NULL)) {
276 kw = match_keyword(name, name_len);
277 switch (kw) {
278 case YANG_PREFIX:
279 /* TODO parse prefix */
280 case YANG_DESCRIPTION:
281 /* TODO parse description */
282 case YANG_REFERENCE:
283 /* TODO parse reference */
284 case YANG_REVISION_DATE:
285 /* TODO parse revision date */
286 case YANG_CUSTOM:
287 /* TODO parse extension */
288 default:
289 /* TODO log error */
290 return LY_EVALID;
291 }
292 }
293
294 /* TODO add log macro and log error */
295 LY_CHECK_RET(!imp->prefix);
296 return ret;
297}
298
David Sedlákd5318ee2019-02-15 10:14:50 +0100299/**
300 * @brief Parse module substatements.
301 *
302 * @param[in] xml_ctx xml context.
303 * @param[in, out] data Data to read from.
304 * @param[out] mod Parsed module structure
305 *
306 * @return LY_ERR values.
307 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100308LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100309parse_mod(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200310{
David Sedlákf3b24f62018-11-02 10:40:47 +0100311 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100312 enum yang_keyword kw = YANG_NONE;
David Sedláke4889912018-11-02 09:52:40 +0100313 const char *prefix, *name;
David Sedlák3b4db242018-10-19 16:11:01 +0200314 size_t prefix_len, name_len;
David Sedlák4b4713f2019-02-15 13:47:45 +0100315 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
David Sedlák3b4db242018-10-19 16:11:01 +0200316
David Sedlákf3b24f62018-11-02 10:40:47 +0100317 char *buf = NULL, *out = NULL;
318 size_t buf_len = 0, out_len = 0;
319 int dynamic;
320
David Sedlák3017da42019-02-15 09:48:04 +0100321 /* check if module has argument "name" */
David Sedlák3b4db242018-10-19 16:11:01 +0200322 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
323 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák872c7b42018-10-26 13:15:20 +0200324 if (match_argument_name(name, name_len) != YIN_ARG_NAME) {
David Sedlákc10e7902018-12-17 02:17:59 +0100325 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 +0200326 }
327
David Sedlákf3b24f62018-11-02 10:40:47 +0100328 /* read module name */
David Sedlák4a4c0722018-11-26 17:03:10 +0100329 if (xml_ctx->status != LYXML_ATTR_CONTENT) {
David Sedlákc10e7902018-12-17 02:17:59 +0100330 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 +0100331 }
David Sedlák3b4db242018-10-19 16:11:01 +0200332 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
333 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák3017da42019-02-15 09:48:04 +0100334 (*mod)->mod->name = lydict_insert(xml_ctx->ctx, out, out_len);
335 LY_CHECK_ERR_RET(!(*mod)->mod->name, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlákf3b24f62018-11-02 10:40:47 +0100336
David Sedlákc10e7902018-12-17 02:17:59 +0100337 /* read all attributes and their content only for testing */
David Sedlák4a4c0722018-11-26 17:03:10 +0100338 while (xml_ctx->status == LYXML_ATTRIBUTE) {
339 lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákc10e7902018-12-17 02:17:59 +0100340 while (xml_ctx->status == LYXML_ATTR_CONTENT) {
341 lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák4a4c0722018-11-26 17:03:10 +0100342 }
343 }
344
David Sedlák736fd0d2019-02-15 16:06:31 +0100345 /* loop over all elements and parse them */
David Sedlák4a4c0722018-11-26 17:03:10 +0100346 while (xml_ctx->status == LYXML_ELEMENT || xml_ctx->status == LYXML_ELEM_CONTENT) {
David Sedlák4b4713f2019-02-15 13:47:45 +0100347
348/* TODO ADD error log to macro */
349#define CHECK_ORDER(SECTION) \
350 if (mod_stmt > SECTION) {return LY_EVALID;}mod_stmt = SECTION
351
352 switch (kw) {
353 /* module header */
354 case YANG_NAMESPACE:
355 case YANG_PREFIX:
356 CHECK_ORDER(Y_MOD_MODULE_HEADER);
357 break;
358 case YANG_YANG_VERSION:
359 CHECK_ORDER(Y_MOD_MODULE_HEADER);
360 break;
361 /* linkage */
362 case YANG_INCLUDE:
363 case YANG_IMPORT:
364 CHECK_ORDER(Y_MOD_LINKAGE);
365 break;
366 /* meta */
367 case YANG_ORGANIZATION:
368 case YANG_CONTACT:
369 case YANG_DESCRIPTION:
370 case YANG_REFERENCE:
371 CHECK_ORDER(Y_MOD_META);
372 break;
373
374 /* revision */
375 case YANG_REVISION:
376 CHECK_ORDER(Y_MOD_REVISION);
377 break;
378 /* body */
379 case YANG_ANYDATA:
380 case YANG_ANYXML:
381 case YANG_AUGMENT:
382 case YANG_CHOICE:
383 case YANG_CONTAINER:
384 case YANG_DEVIATION:
385 case YANG_EXTENSION:
386 case YANG_FEATURE:
387 case YANG_GROUPING:
388 case YANG_IDENTITY:
389 case YANG_LEAF:
390 case YANG_LEAF_LIST:
391 case YANG_LIST:
392 case YANG_NOTIFICATION:
393 case YANG_RPC:
394 case YANG_TYPEDEF:
395 case YANG_USES:
396 case YANG_CUSTOM:
397 mod_stmt = Y_MOD_BODY;
398 break;
399 default:
400 /* error will be handled in the next switch */
401 break;
402 }
403#undef CHECK_ORDER
404
David Sedlák4a4c0722018-11-26 17:03:10 +0100405 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák4a4c0722018-11-26 17:03:10 +0100406 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák94de2aa2019-02-15 12:42:11 +0100407 kw = match_keyword(name, name_len);
David Sedlák4a4c0722018-11-26 17:03:10 +0100408
409 switch (kw) {
David Sedlák736fd0d2019-02-15 16:06:31 +0100410
411 /* module header */
412 case YANG_NAMESPACE:
413 LY_CHECK_RET(parse_namespace(xml_ctx, data, mod));
David Sedlák4a4c0722018-11-26 17:03:10 +0100414 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100415 case YANG_PREFIX:
416 LY_CHECK_RET(parse_prefix(xml_ctx, data, mod));
417 /* TODO change lysp_check_prefix function to work with ctx and not parser_ctx */
418 //LY_CHECK_RET(lysp_check_prefix(&xml_ctx->ctx, *mod_p, &((*mod_p)->prefix)), LY_EVALID);
David Sedláka5004e62018-12-16 23:54:47 +0100419 break;
David Sedlák4a4c0722018-11-26 17:03:10 +0100420
David Sedlák736fd0d2019-02-15 16:06:31 +0100421 /* linkage */
422 case YANG_IMPORT:
423 yin_parse_import(xml_ctx, (*mod)->mod->prefix, data, &(*mod)->imports);
424
425
426 default:
427 /* error */
David Sedlák4a4c0722018-11-26 17:03:10 +0100428 break;
429 }
430 }
431
David Sedlákf3b24f62018-11-02 10:40:47 +0100432 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200433}
434
David Sedlákd5318ee2019-02-15 10:14:50 +0100435/**
436 * @brief Parse yin submodule.
437 *
438 * @param[in] ctx Context of YANG schemas.
439 * @param[in] data Data to read from.
440 * @param[out] submod Module to write to.
441 *
442 * @return LY_ERR values.
443 */
444LY_ERR
445yin_parse_submodule(struct ly_ctx *ctx, const char *data, struct lysp_submodule **submod)
446{
447 LY_ERR ret = LY_SUCCESS;
448 enum yang_keyword kw = YANG_NONE;
449 struct lyxml_context xml_ctx;
450 struct lysp_submodule *mod_p = NULL;
451 const char *prefix, *name;
452 size_t prefix_len, name_len;
David Sedlák3017da42019-02-15 09:48:04 +0100453
David Sedlákd5318ee2019-02-15 10:14:50 +0100454 /* initialize xml context */
455 memset(&xml_ctx, 0, sizeof xml_ctx);
456 xml_ctx.ctx = ctx;
457 xml_ctx.line = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100458
David Sedlákd5318ee2019-02-15 10:14:50 +0100459 /* check submodule */
460 ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
461 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák94de2aa2019-02-15 12:42:11 +0100462 kw = match_keyword(name, name_len);
David Sedlákd5318ee2019-02-15 10:14:50 +0100463 if (kw == YANG_MODULE) {
464 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
465 ret = LY_EINVAL;
466 goto cleanup;
467 } else if (kw != YANG_SUBMODULE) {
468 /* TODO log error using LOGVAL_YIN macro */
469 ret = LY_EVALID;
470 goto cleanup;
471 }
David Sedlák3017da42019-02-15 09:48:04 +0100472
David Sedlákd5318ee2019-02-15 10:14:50 +0100473 /* allocate module */
474 mod_p = calloc(1, sizeof *mod_p);
475 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
476 mod_p->parsing = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100477
David Sedlákd5318ee2019-02-15 10:14:50 +0100478 /* parser submodule substatements */
479 //ret = parse_submod(&xml_ctx, &data, mod_p);
480 LY_CHECK_GOTO(ret, cleanup);
David Sedlák3017da42019-02-15 09:48:04 +0100481
David Sedlákd5318ee2019-02-15 10:14:50 +0100482 mod_p->parsing = 0;
483 *submod = mod_p;
David Sedlák3017da42019-02-15 09:48:04 +0100484
David Sedlákd5318ee2019-02-15 10:14:50 +0100485cleanup:
486 if (ret) {
487 lysp_submodule_free(ctx, mod_p);
488 }
David Sedlák3017da42019-02-15 09:48:04 +0100489
David Sedlákd5318ee2019-02-15 10:14:50 +0100490 lyxml_context_clear(&xml_ctx);
491 return ret;
492}
David Sedlák3017da42019-02-15 09:48:04 +0100493
David Sedlákd5318ee2019-02-15 10:14:50 +0100494/**
495 * @brief Parse yin module.
496 *
497 * @param[in] ctx Context of YANG schemas.
498 * @param[in] data Data to read from.
499 * @param[out] mod Module to write to.
500 *
501 * @return LY_ERR values.
502 */
David Sedlák3b4db242018-10-19 16:11:01 +0200503LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100504yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200505{
David Sedláke4889912018-11-02 09:52:40 +0100506 LY_ERR ret = LY_SUCCESS;
507 enum yang_keyword kw = YANG_NONE;
David Sedlák3b4db242018-10-19 16:11:01 +0200508 struct lyxml_context xml_ctx;
David Sedlák3017da42019-02-15 09:48:04 +0100509 struct lysp_module *mod_p = NULL;
510 const char *prefix, *name;
511 size_t prefix_len, name_len;
David Sedlák3b4db242018-10-19 16:11:01 +0200512
David Sedlák3017da42019-02-15 09:48:04 +0100513 /* initialize xml context */
David Sedláke4889912018-11-02 09:52:40 +0100514 memset(&xml_ctx, 0, sizeof xml_ctx);
515 xml_ctx.ctx = ctx;
516 xml_ctx.line = 1;
517
David Sedlák3017da42019-02-15 09:48:04 +0100518 /* check submodule */
David Sedláke4889912018-11-02 09:52:40 +0100519 ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák3017da42019-02-15 09:48:04 +0100520 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák94de2aa2019-02-15 12:42:11 +0100521 kw = match_keyword(name, name_len);
David Sedláke4889912018-11-02 09:52:40 +0100522 if (kw == YANG_SUBMODULE) {
David Sedlák3017da42019-02-15 09:48:04 +0100523 LOGERR(ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
524 ret = LY_EINVAL;
525 goto cleanup;
526 } else if (kw != YANG_MODULE) {
527 /* TODO log error using LOGVAL_YIN macro */
528 ret = LY_EVALID;
529 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +0100530 }
531
David Sedlák3017da42019-02-15 09:48:04 +0100532 /* allocate module */
533 mod_p = calloc(1, sizeof *mod_p);
534 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
535 mod_p->mod = mod;
536 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +0100537
David Sedlák3017da42019-02-15 09:48:04 +0100538 /* parser module substatements */
539 ret = parse_mod(&xml_ctx, &data, &mod_p);
540 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +0100541
David Sedlák3017da42019-02-15 09:48:04 +0100542 mod_p->parsing = 0;
543 mod->parsed = mod_p;
544
545cleanup:
546 if (ret) {
547 lysp_module_free(mod_p);
548 }
549
David Sedlák2e411422018-12-17 02:35:39 +0100550 lyxml_context_clear(&xml_ctx);
551 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200552}