blob: 7d406f5bc823bb6a3525b26981e7c873e710870a [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ákecf5eb82019-06-03 14:12:44 +020014#include "common.h"
15
David Sedlák3b4db242018-10-19 16:11:01 +020016#include <stdio.h>
17#include <stdlib.h>
18#include <unistd.h>
David Sedlák872c7b42018-10-26 13:15:20 +020019#include <string.h>
David Sedlákf824ad52018-10-14 23:58:15 +020020
David Sedlákf824ad52018-10-14 23:58:15 +020021#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020022#include "dict.h"
David Sedlák3b4db242018-10-19 16:11:01 +020023#include "xml.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020024#include "tree.h"
25#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020026#include "tree_schema_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020027#include "parser_yin.h"
David Sedlákf824ad52018-10-14 23:58:15 +020028
David Sedlákc136b972019-03-08 13:39:06 +010029/**
David Sedlákd5318ee2019-02-15 10:14:50 +010030 * @brief Match argument name.
31 *
32 * @param[in] name String representing name.
33 * @param[in] len Lenght of the name.
34 *
35 * @reurn YIN_ARGUMENT value.
36 */
David Sedlák872c7b42018-10-26 13:15:20 +020037enum YIN_ARGUMENT
David Sedláke4889912018-11-02 09:52:40 +010038match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020039{
David Sedláka7406952019-04-05 10:33:07 +020040 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +020041 size_t already_read = 0;
David Sedláka7406952019-04-05 10:33:07 +020042 LY_CHECK_RET(len == 0, YIN_ARG_UNKNOWN);
David Sedlák3b4db242018-10-19 16:11:01 +020043
David Sedlák94de2aa2019-02-15 12:42:11 +010044#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
45#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +010046#define IF_ARG_PREFIX_END }
47
David Sedlák1c8b2702019-02-22 11:03:02 +010048 switch (*name) {
David Sedlák18730132019-03-15 15:51:34 +010049 case 'x':
50 already_read += 1;
51 IF_ARG("mlns", 4, YIN_ARG_XMLNS);
52 break;
David Sedlák94de2aa2019-02-15 12:42:11 +010053 case 'c':
54 already_read += 1;
55 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +020056 break;
David Sedlák872c7b42018-10-26 13:15:20 +020057
David Sedlák94de2aa2019-02-15 12:42:11 +010058 case 'd':
59 already_read += 1;
60 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +020061 break;
David Sedlák872c7b42018-10-26 13:15:20 +020062
David Sedlák94de2aa2019-02-15 12:42:11 +010063 case 'm':
64 already_read += 1;
65 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +020066 break;
67
David Sedlák94de2aa2019-02-15 12:42:11 +010068 case 'n':
69 already_read += 1;
70 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +020071 break;
72
David Sedlák94de2aa2019-02-15 12:42:11 +010073 case 't':
74 already_read += 1;
75 IF_ARG_PREFIX("a", 1)
76 IF_ARG("g", 1, YIN_ARG_TAG)
77 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
78 IF_ARG_PREFIX_END
79 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +020080 break;
David Sedlák872c7b42018-10-26 13:15:20 +020081
David Sedlák94de2aa2019-02-15 12:42:11 +010082 case 'u':
83 already_read += 1;
84 IF_ARG("ri", 2, YIN_ARG_URI)
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 'v':
88 already_read += 1;
89 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +020090 break;
91 }
92
David Sedlákc10e7902018-12-17 02:17:59 +010093 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +020094 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +020095 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +020096 }
97
David Sedlák18730132019-03-15 15:51:34 +010098#undef IF_ARG
99#undef IF_ARG_PREFIX
100#undef IF_ARG_PREFIX_END
101
David Sedlák872c7b42018-10-26 13:15:20 +0200102 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200103}
104
David Sedlák18730132019-03-15 15:51:34 +0100105/**
David Sedlákecf5eb82019-06-03 14:12:44 +0200106 * @brief parse yin argument
David Sedláka7406952019-04-05 10:33:07 +0200107 *
108 * @param[in] xml_ctx XML parser context.
109 * @param[in, out] data Data to read from.
110 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without special arguments).
111 * @param[out] arg_val Where value of argument should be stored. Can be NULL if arg_type is spedified as YIN_ARG_NONE.
David Sedláka7406952019-04-05 10:33:07 +0200112 */
113static LY_ERR
David Sedlákecf5eb82019-06-03 14:12:44 +0200114yin_parse_attribute(struct lyxml_context *xml_ctx, const char **data, enum YIN_ARGUMENT arg_type, const char **arg_val)
David Sedláka7406952019-04-05 10:33:07 +0200115{
116 LY_ERR ret = LY_SUCCESS;
117 const char *prefix, *name;
118 size_t prefix_len, name_len;
119
120 char *buf = NULL, *out = NULL;
121 size_t buf_len = 0, out_len = 0;
122 int dynamic;
123 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
124
125 while (xml_ctx->status == LYXML_ATTRIBUTE) {
126 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
127 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
128
129 arg = match_argument_name(name, name_len);
130
David Sedlákecf5eb82019-06-03 14:12:44 +0200131 if (arg == arg_type) {
David Sedláka7406952019-04-05 10:33:07 +0200132 LY_CHECK_RET(ret);
133 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
134 LY_CHECK_RET(ret);
135 *arg_val = lydict_insert(xml_ctx->ctx, out, out_len);
136 LY_CHECK_ERR_RET(!(*arg_val), LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlákecf5eb82019-06-03 14:12:44 +0200137 } else if (arg_type == YIN_ARG_NONE) {
138 continue;
David Sedláka7406952019-04-05 10:33:07 +0200139 } else {
David Sedlákecf5eb82019-06-03 14:12:44 +0200140 /* unrecognized or unexpected attribute */
141 if (name) {
David Sedláka7406952019-04-05 10:33:07 +0200142 LOGERR(xml_ctx->ctx, LY_EDENIED, "Invalid argument in namespace element");
143 return LY_EVALID;
144 }
145 }
146 }
147
148 return LY_SUCCESS;
149}
150
151/**
David Sedlák0daba9a2019-03-22 14:07:49 +0100152 * @brief Parse content of whole element as text.
153 *
154 * @param[in] xml_ctx Xml context.
155 * @param[in] data Data to read from.
156 * @param[out] value Where content of element should be stored.
157 */
158LY_ERR
David Sedlákecf5eb82019-06-03 14:12:44 +0200159parse_text_element(struct lyxml_context *xml_ctx, const char **data, const char **value)
David Sedlák0daba9a2019-03-22 14:07:49 +0100160{
161 LY_ERR ret = LY_SUCCESS;
162 char *buf = NULL, *out = NULL;
David Sedlákecf5eb82019-06-03 14:12:44 +0200163 size_t buf_len = 0, out_len = 0;
David Sedlák0daba9a2019-03-22 14:07:49 +0100164 int dynamic;
David Sedlák0daba9a2019-03-22 14:07:49 +0100165
David Sedlákecf5eb82019-06-03 14:12:44 +0200166 ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_NONE, NULL);
David Sedláka7406952019-04-05 10:33:07 +0200167 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlák0daba9a2019-03-22 14:07:49 +0100168 LY_CHECK_RET(xml_ctx->status != LYXML_ELEM_CONTENT, LY_EVALID);
169
170 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
171 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
172 LY_CHECK_RET(ret);
173 *value = lydict_insert(xml_ctx->ctx, out, out_len);
174 LY_CHECK_ERR_RET(!(*value), LOGMEM(xml_ctx->ctx), LY_EMEM);
175 }
176
David Sedlák6b7ac2d2019-03-22 14:40:29 +0100177 return LY_SUCCESS;
David Sedlák0daba9a2019-03-22 14:07:49 +0100178}
179
David Sedlákd5318ee2019-02-15 10:14:50 +0100180/**
181 * @brief Parse namespace statement.
182 *
183 * @param[in] xml_ctx xml context.
184 * @param[in, out] data Data to read from.
David Sedlák81e04022019-04-05 15:05:46 +0200185 * @param[in, out] namespace Where namespace value should be stored.
David Sedlákd5318ee2019-02-15 10:14:50 +0100186 *
187 * @return LY_ERR values.
188 */
David Sedláka5004e62018-12-16 23:54:47 +0100189LY_ERR
David Sedlák81e04022019-04-05 15:05:46 +0200190parse_namespace(struct lyxml_context *xml_ctx, const char **data, const char **namespace)
David Sedlák4a4c0722018-11-26 17:03:10 +0100191{
192 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100193
David Sedlákecf5eb82019-06-03 14:12:44 +0200194 ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_URI, namespace);
David Sedláka7406952019-04-05 10:33:07 +0200195 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlák4a4c0722018-11-26 17:03:10 +0100196
David Sedlák4a4c0722018-11-26 17:03:10 +0100197 return LY_SUCCESS;
198}
199
David Sedlákd5318ee2019-02-15 10:14:50 +0100200/**
201 * @brief Parse prefix statement.
202 *
203 * @param[in] xml_ctx Xml context.
204 * @param[in, out] data Data to reda from.
David Sedlák81e04022019-04-05 15:05:46 +0200205 * @param[out] prefix Where to store prefix value.
David Sedlákd5318ee2019-02-15 10:14:50 +0100206 *
207 * @return LY_ERR values.
208 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100209LY_ERR
David Sedlák81e04022019-04-05 15:05:46 +0200210parse_prefix(struct lyxml_context *xml_ctx, const char **data, const char **prefix)
David Sedlák4a4c0722018-11-26 17:03:10 +0100211{
212 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100213
David Sedlákcd0c9512019-03-29 13:23:06 +0100214 /* parse attributes */
David Sedlákecf5eb82019-06-03 14:12:44 +0200215 ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_VALUE, prefix);
David Sedlákcd0c9512019-03-29 13:23:06 +0100216 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlákecf5eb82019-06-03 14:12:44 +0200217
David Sedlákcd0c9512019-03-29 13:23:06 +0100218 return ret;
David Sedlák4a4c0722018-11-26 17:03:10 +0100219}
220
David Sedlák81e04022019-04-05 15:05:46 +0200221static LY_ERR
222yin_parse_revision_date(struct lyxml_context *xml_ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
223{
224 LY_ERR ret = LY_SUCCESS;
David Sedlákcd0c9512019-03-29 13:23:06 +0100225
David Sedlák81e04022019-04-05 15:05:46 +0200226 if (rev[0]) {
227 LOGVAL_YANG(xml_ctx, LY_VCODE_DUPSTMT, "revision-date");
228 return LY_EVALID;
229 }
230
David Sedlákecf5eb82019-06-03 14:12:44 +0200231 ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_DATE, (const char **)&rev);
David Sedlák81e04022019-04-05 15:05:46 +0200232 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlákecf5eb82019-06-03 14:12:44 +0200233 LY_CHECK_RET(lysp_check_date((struct lys_parser_ctx *)xml_ctx, rev, strlen(rev), "revision-date") != LY_SUCCESS, LY_EVALID);
David Sedlák81e04022019-04-05 15:05:46 +0200234
David Sedlák81e04022019-04-05 15:05:46 +0200235 return ret;
236}
David Sedlákcd0c9512019-03-29 13:23:06 +0100237
David Sedlák736fd0d2019-02-15 16:06:31 +0100238static LY_ERR
David Sedlák81e04022019-04-05 15:05:46 +0200239yin_parse_import(struct lyxml_context *xml_ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
David Sedlák736fd0d2019-02-15 16:06:31 +0100240{
241 LY_ERR ret = LY_SUCCESS;
242 enum yang_keyword kw;
243 struct lysp_import *imp;
244 const char *prefix, *name;
245 size_t prefix_len, name_len;
246
David Sedlák81e04022019-04-05 15:05:46 +0200247 /* allocate sized array for imports */
248 LY_ARRAY_NEW_RET(xml_ctx->ctx, *imports, imp, LY_EVALID);
David Sedlák736fd0d2019-02-15 16:06:31 +0100249
David Sedláka7406952019-04-05 10:33:07 +0200250 /* parse import attributes */
David Sedlákecf5eb82019-06-03 14:12:44 +0200251 ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_MODULE, &imp->name);
David Sedlák736fd0d2019-02-15 16:06:31 +0100252 while ((ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len) == LY_SUCCESS && name != NULL)) {
David Sedlák18730132019-03-15 15:51:34 +0100253 kw = match_keyword(name, name_len, prefix_len);
David Sedlák736fd0d2019-02-15 16:06:31 +0100254 switch (kw) {
255 case YANG_PREFIX:
David Sedlák81e04022019-04-05 15:05:46 +0200256 LY_CHECK_ERR_RET(imp->prefix, LOGVAL_YANG(xml_ctx, LY_VCODE_DUPSTMT, "prefix"), LY_EVALID);
257 parse_prefix(xml_ctx, data, &imp->prefix);
David Sedlákcd0c9512019-03-29 13:23:06 +0100258 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100259 case YANG_DESCRIPTION:
David Sedlák81e04022019-04-05 15:05:46 +0200260 LY_CHECK_ERR_RET(imp->dsc, LOGVAL_YANG(xml_ctx, LY_VCODE_DUPSTMT, "description"), LY_EVALID);
David Sedlákecf5eb82019-06-03 14:12:44 +0200261 parse_text_element(xml_ctx, data, &imp->dsc);
David Sedlákcd0c9512019-03-29 13:23:06 +0100262 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100263 case YANG_REFERENCE:
David Sedlák81e04022019-04-05 15:05:46 +0200264 LY_CHECK_ERR_RET(imp->ref, LOGVAL_YANG(xml_ctx, LY_VCODE_DUPSTMT, "reference"), LY_EVALID);
David Sedlákecf5eb82019-06-03 14:12:44 +0200265 parse_text_element(xml_ctx, data, &imp->ref);
David Sedlákcd0c9512019-03-29 13:23:06 +0100266 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100267 case YANG_REVISION_DATE:
David Sedlákecf5eb82019-06-03 14:12:44 +0200268 yin_parse_revision_date(xml_ctx, data, imp->rev, &imp->exts);
David Sedlák3a55bc12019-06-03 08:57:29 +0200269 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100270 case YANG_CUSTOM:
271 /* TODO parse extension */
David Sedlák3a55bc12019-06-03 08:57:29 +0200272 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100273 default:
274 /* TODO log error */
275 return LY_EVALID;
276 }
277 }
278
279 /* TODO add log macro and log error */
280 LY_CHECK_RET(!imp->prefix);
281 return ret;
282}
283
David Sedlákd5318ee2019-02-15 10:14:50 +0100284/**
285 * @brief Parse module substatements.
286 *
287 * @param[in] xml_ctx xml context.
288 * @param[in, out] data Data to read from.
289 * @param[out] mod Parsed module structure
290 *
291 * @return LY_ERR values.
292 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100293LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100294parse_mod(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200295{
David Sedlákf3b24f62018-11-02 10:40:47 +0100296 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100297 enum yang_keyword kw = YANG_NONE;
David Sedláke4889912018-11-02 09:52:40 +0100298 const char *prefix, *name;
David Sedlák3b4db242018-10-19 16:11:01 +0200299 size_t prefix_len, name_len;
David Sedlák4b4713f2019-02-15 13:47:45 +0100300 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
David Sedláka7406952019-04-05 10:33:07 +0200301 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
David Sedlák3b4db242018-10-19 16:11:01 +0200302
David Sedlákf3b24f62018-11-02 10:40:47 +0100303 char *buf = NULL, *out = NULL;
304 size_t buf_len = 0, out_len = 0;
305 int dynamic;
306
David Sedlák18730132019-03-15 15:51:34 +0100307 /* parse module attributes */
308 while (xml_ctx->status == LYXML_ATTRIBUTE) {
309 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
310 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
311
312 arg = match_argument_name(name, name_len);
313
314 switch (arg) {
David Sedlák18730132019-03-15 15:51:34 +0100315 case YIN_ARG_NAME:
316 /* check for multiple definitions of name */
317 LY_CHECK_ERR_RET((*mod)->mod->name, LOGVAL_YANG(xml_ctx, LYVE_SYNTAX_YIN, "Duplicit definition of module name \"%s\"", (*mod)->mod->name), LY_EEXIST);
318
319 /* read module name */
320 if (xml_ctx->status != LYXML_ATTR_CONTENT) {
321 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Missing value of argument \"name\".");
322 }
323 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
324 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
325 (*mod)->mod->name = lydict_insert(xml_ctx->ctx, out, out_len);
326 LY_CHECK_ERR_RET(!(*mod)->mod->name, LOGMEM(xml_ctx->ctx), LY_EMEM);
327 break;
David Sedlákecf5eb82019-06-03 14:12:44 +0200328
David Sedlák18730132019-03-15 15:51:34 +0100329 default:
David Sedlákecf5eb82019-06-03 14:12:44 +0200330 /* unrecognized attribute */
331 /* unrecognized or unexpected attribute */
332 /* TODO probably still can be from extension */
333 if (arg != YIN_ARG_UNKNOWN || name) {
David Sedlák18730132019-03-15 15:51:34 +0100334 LOGERR(xml_ctx->ctx, LY_EDENIED, "Invalid argument in module element");
335 return LY_EVALID;
336 }
David Sedlákecf5eb82019-06-03 14:12:44 +0200337
David Sedlák18730132019-03-15 15:51:34 +0100338 break;
339 }
David Sedlák3b4db242018-10-19 16:11:01 +0200340 }
341
David Sedlák18730132019-03-15 15:51:34 +0100342 LY_CHECK_ERR_RET(!(*mod)->mod->name, LOGVAL_YANG(xml_ctx, LYVE_SYNTAX_YIN, "Missing argument name of a module", (*mod)->mod->name), LY_ENOTFOUND);
David Sedlákf3b24f62018-11-02 10:40:47 +0100343
David Sedlákc136b972019-03-08 13:39:06 +0100344 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák18730132019-03-15 15:51:34 +0100345 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 +0100346
David Sedlák736fd0d2019-02-15 16:06:31 +0100347 /* loop over all elements and parse them */
David Sedlákc136b972019-03-08 13:39:06 +0100348 while (xml_ctx->status != LYXML_END) {
David Sedlák4b4713f2019-02-15 13:47:45 +0100349/* TODO ADD error log to macro */
350#define CHECK_ORDER(SECTION) \
351 if (mod_stmt > SECTION) {return LY_EVALID;}mod_stmt = SECTION
352
353 switch (kw) {
354 /* module header */
355 case YANG_NAMESPACE:
356 case YANG_PREFIX:
357 CHECK_ORDER(Y_MOD_MODULE_HEADER);
358 break;
359 case YANG_YANG_VERSION:
360 CHECK_ORDER(Y_MOD_MODULE_HEADER);
361 break;
362 /* linkage */
363 case YANG_INCLUDE:
364 case YANG_IMPORT:
365 CHECK_ORDER(Y_MOD_LINKAGE);
366 break;
367 /* meta */
368 case YANG_ORGANIZATION:
369 case YANG_CONTACT:
370 case YANG_DESCRIPTION:
371 case YANG_REFERENCE:
372 CHECK_ORDER(Y_MOD_META);
373 break;
374
375 /* revision */
376 case YANG_REVISION:
377 CHECK_ORDER(Y_MOD_REVISION);
378 break;
379 /* body */
380 case YANG_ANYDATA:
381 case YANG_ANYXML:
382 case YANG_AUGMENT:
383 case YANG_CHOICE:
384 case YANG_CONTAINER:
385 case YANG_DEVIATION:
386 case YANG_EXTENSION:
387 case YANG_FEATURE:
388 case YANG_GROUPING:
389 case YANG_IDENTITY:
390 case YANG_LEAF:
391 case YANG_LEAF_LIST:
392 case YANG_LIST:
393 case YANG_NOTIFICATION:
394 case YANG_RPC:
395 case YANG_TYPEDEF:
396 case YANG_USES:
397 case YANG_CUSTOM:
398 mod_stmt = Y_MOD_BODY;
399 break;
400 default:
401 /* error will be handled in the next switch */
402 break;
403 }
404#undef CHECK_ORDER
405
David Sedlák4a4c0722018-11-26 17:03:10 +0100406 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákc136b972019-03-08 13:39:06 +0100407 LY_CHECK_RET(ret != LY_SUCCESS, LY_EMEM);
David Sedlák4a4c0722018-11-26 17:03:10 +0100408
David Sedlákc136b972019-03-08 13:39:06 +0100409 if (name) {
David Sedlák18730132019-03-15 15:51:34 +0100410 kw = match_keyword(name, name_len, prefix_len);
David Sedlákc136b972019-03-08 13:39:06 +0100411 switch (kw) {
David Sedlák736fd0d2019-02-15 16:06:31 +0100412
David Sedlákc136b972019-03-08 13:39:06 +0100413 /* module header */
414 case YANG_NAMESPACE:
David Sedlák81e04022019-04-05 15:05:46 +0200415 LY_CHECK_RET(parse_namespace(xml_ctx, data, &(*mod)->mod->ns));
David Sedlákc136b972019-03-08 13:39:06 +0100416 break;
417 case YANG_PREFIX:
David Sedlák81e04022019-04-05 15:05:46 +0200418 LY_CHECK_RET(parse_prefix(xml_ctx, data, &(*mod)->mod->prefix));
David Sedlákc136b972019-03-08 13:39:06 +0100419 break;
David Sedlák4a4c0722018-11-26 17:03:10 +0100420
David Sedlákc136b972019-03-08 13:39:06 +0100421 /* linkage */
422 case YANG_IMPORT:
David Sedlák81e04022019-04-05 15:05:46 +0200423 yin_parse_import(xml_ctx, (*mod)->mod->prefix, data, &(*mod)->imports);
David Sedlákc136b972019-03-08 13:39:06 +0100424 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100425
David Sedlákc136b972019-03-08 13:39:06 +0100426 /* meta */
427 case YANG_ORGANIZATION:
David Sedlákecf5eb82019-06-03 14:12:44 +0200428 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->org));
David Sedlákc136b972019-03-08 13:39:06 +0100429 break;
430 case YANG_CONTACT:
David Sedlákecf5eb82019-06-03 14:12:44 +0200431 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->contact));
David Sedlákc136b972019-03-08 13:39:06 +0100432 break;
433 case YANG_DESCRIPTION:
David Sedlákecf5eb82019-06-03 14:12:44 +0200434 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->dsc));
David Sedlákc136b972019-03-08 13:39:06 +0100435 break;
436 case YANG_REFERENCE:
David Sedlákecf5eb82019-06-03 14:12:44 +0200437 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->ref));
David Sedlákc136b972019-03-08 13:39:06 +0100438 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100439
David Sedlákc136b972019-03-08 13:39:06 +0100440 default:
David Sedlák18730132019-03-15 15:51:34 +0100441 return LY_EVALID;
David Sedlákc136b972019-03-08 13:39:06 +0100442 break;
443 }
David Sedlák4a4c0722018-11-26 17:03:10 +0100444 }
445 }
446
David Sedlákf3b24f62018-11-02 10:40:47 +0100447 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200448}
449
David Sedlákd5318ee2019-02-15 10:14:50 +0100450/**
451 * @brief Parse yin submodule.
452 *
453 * @param[in] ctx Context of YANG schemas.
454 * @param[in] data Data to read from.
455 * @param[out] submod Module to write to.
456 *
457 * @return LY_ERR values.
458 */
459LY_ERR
460yin_parse_submodule(struct ly_ctx *ctx, const char *data, struct lysp_submodule **submod)
461{
462 LY_ERR ret = LY_SUCCESS;
463 enum yang_keyword kw = YANG_NONE;
464 struct lyxml_context xml_ctx;
465 struct lysp_submodule *mod_p = NULL;
466 const char *prefix, *name;
467 size_t prefix_len, name_len;
David Sedlák3017da42019-02-15 09:48:04 +0100468
David Sedlákd5318ee2019-02-15 10:14:50 +0100469 /* initialize xml context */
470 memset(&xml_ctx, 0, sizeof xml_ctx);
471 xml_ctx.ctx = ctx;
472 xml_ctx.line = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100473
David Sedlákd5318ee2019-02-15 10:14:50 +0100474 /* check submodule */
475 ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
476 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák18730132019-03-15 15:51:34 +0100477 kw = match_keyword(name, name_len, prefix_len);
David Sedlákd5318ee2019-02-15 10:14:50 +0100478 if (kw == YANG_MODULE) {
479 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
480 ret = LY_EINVAL;
481 goto cleanup;
482 } else if (kw != YANG_SUBMODULE) {
David Sedlák0a875b42019-03-07 22:24:05 +0100483 LOGVAL_YANG(&xml_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
484 ly_stmt2str(kw));
David Sedlákd5318ee2019-02-15 10:14:50 +0100485 ret = LY_EVALID;
486 goto cleanup;
487 }
David Sedlák3017da42019-02-15 09:48:04 +0100488
David Sedlákd5318ee2019-02-15 10:14:50 +0100489 /* allocate module */
490 mod_p = calloc(1, sizeof *mod_p);
491 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
492 mod_p->parsing = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100493
David Sedlákd5318ee2019-02-15 10:14:50 +0100494 /* parser submodule substatements */
495 //ret = parse_submod(&xml_ctx, &data, mod_p);
496 LY_CHECK_GOTO(ret, cleanup);
David Sedlák3017da42019-02-15 09:48:04 +0100497
David Sedlákd5318ee2019-02-15 10:14:50 +0100498 mod_p->parsing = 0;
499 *submod = mod_p;
David Sedlák3017da42019-02-15 09:48:04 +0100500
David Sedlákd5318ee2019-02-15 10:14:50 +0100501cleanup:
502 if (ret) {
503 lysp_submodule_free(ctx, mod_p);
504 }
David Sedlák3017da42019-02-15 09:48:04 +0100505
David Sedlákd5318ee2019-02-15 10:14:50 +0100506 lyxml_context_clear(&xml_ctx);
507 return ret;
508}
David Sedlák3017da42019-02-15 09:48:04 +0100509
David Sedlákd5318ee2019-02-15 10:14:50 +0100510/**
511 * @brief Parse yin module.
512 *
513 * @param[in] ctx Context of YANG schemas.
514 * @param[in] data Data to read from.
515 * @param[out] mod Module to write to.
516 *
517 * @return LY_ERR values.
518 */
David Sedlák3b4db242018-10-19 16:11:01 +0200519LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100520yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200521{
David Sedláke4889912018-11-02 09:52:40 +0100522 LY_ERR ret = LY_SUCCESS;
523 enum yang_keyword kw = YANG_NONE;
David Sedlákecf5eb82019-06-03 14:12:44 +0200524 struct lys_parser_ctx parser_ctx;
David Sedlákaadab9c2019-04-05 15:01:27 +0200525 struct lyxml_context *xml_ctx = (struct lyxml_context *)&parser_ctx;
David Sedlák3017da42019-02-15 09:48:04 +0100526 struct lysp_module *mod_p = NULL;
527 const char *prefix, *name;
528 size_t prefix_len, name_len;
David Sedlák3b4db242018-10-19 16:11:01 +0200529
David Sedlák3017da42019-02-15 09:48:04 +0100530 /* initialize xml context */
David Sedlákaadab9c2019-04-05 15:01:27 +0200531 memset(&parser_ctx, 0, sizeof parser_ctx);
532 xml_ctx->ctx = ctx;
533 xml_ctx->line = 1;
David Sedláke4889912018-11-02 09:52:40 +0100534
David Sedlák3017da42019-02-15 09:48:04 +0100535 /* check submodule */
David Sedlákaadab9c2019-04-05 15:01:27 +0200536 ret = lyxml_get_element(xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák3017da42019-02-15 09:48:04 +0100537 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák18730132019-03-15 15:51:34 +0100538 kw = match_keyword(name, name_len, prefix_len);
David Sedláke4889912018-11-02 09:52:40 +0100539 if (kw == YANG_SUBMODULE) {
David Sedlák3017da42019-02-15 09:48:04 +0100540 LOGERR(ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
541 ret = LY_EINVAL;
542 goto cleanup;
543 } else if (kw != YANG_MODULE) {
David Sedlákaadab9c2019-04-05 15:01:27 +0200544 LOGVAL_YANG(xml_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
David Sedlák0a875b42019-03-07 22:24:05 +0100545 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +0100546 ret = LY_EVALID;
547 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +0100548 }
549
David Sedlák3017da42019-02-15 09:48:04 +0100550 /* allocate module */
551 mod_p = calloc(1, sizeof *mod_p);
552 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
553 mod_p->mod = mod;
554 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +0100555
David Sedlák3017da42019-02-15 09:48:04 +0100556 /* parser module substatements */
David Sedlákaadab9c2019-04-05 15:01:27 +0200557 ret = parse_mod(xml_ctx, &data, &mod_p);
David Sedlák3017da42019-02-15 09:48:04 +0100558 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +0100559
David Sedlák3017da42019-02-15 09:48:04 +0100560 mod_p->parsing = 0;
561 mod->parsed = mod_p;
562
563cleanup:
564 if (ret) {
565 lysp_module_free(mod_p);
566 }
567
David Sedlákaadab9c2019-04-05 15:01:27 +0200568 lyxml_context_clear(xml_ctx);
David Sedlák2e411422018-12-17 02:35:39 +0100569 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200570}