blob: c060b5be3d1953ac7912a6431643c9e8b3667691 [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ák872c7b42018-10-26 13:15:20 +020029enum YIN_ARGUMENT
David Sedláke4889912018-11-02 09:52:40 +010030match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020031{
David Sedláka7406952019-04-05 10:33:07 +020032 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +020033 size_t already_read = 0;
David Sedláka7406952019-04-05 10:33:07 +020034 LY_CHECK_RET(len == 0, YIN_ARG_UNKNOWN);
David Sedlák3b4db242018-10-19 16:11:01 +020035
David Sedlák94de2aa2019-02-15 12:42:11 +010036#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
37#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +010038#define IF_ARG_PREFIX_END }
39
David Sedlák1c8b2702019-02-22 11:03:02 +010040 switch (*name) {
David Sedlák18730132019-03-15 15:51:34 +010041 case 'x':
42 already_read += 1;
43 IF_ARG("mlns", 4, YIN_ARG_XMLNS);
44 break;
David Sedlák94de2aa2019-02-15 12:42:11 +010045 case 'c':
46 already_read += 1;
47 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +020048 break;
David Sedlák872c7b42018-10-26 13:15:20 +020049
David Sedlák94de2aa2019-02-15 12:42:11 +010050 case 'd':
51 already_read += 1;
52 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +020053 break;
David Sedlák872c7b42018-10-26 13:15:20 +020054
David Sedlák94de2aa2019-02-15 12:42:11 +010055 case 'm':
56 already_read += 1;
57 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +020058 break;
59
David Sedlák94de2aa2019-02-15 12:42:11 +010060 case 'n':
61 already_read += 1;
62 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +020063 break;
64
David Sedlák94de2aa2019-02-15 12:42:11 +010065 case 't':
66 already_read += 1;
67 IF_ARG_PREFIX("a", 1)
68 IF_ARG("g", 1, YIN_ARG_TAG)
69 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
70 IF_ARG_PREFIX_END
71 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +020072 break;
David Sedlák872c7b42018-10-26 13:15:20 +020073
David Sedlák94de2aa2019-02-15 12:42:11 +010074 case 'u':
75 already_read += 1;
76 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +020077 break;
David Sedlák872c7b42018-10-26 13:15:20 +020078
David Sedlák94de2aa2019-02-15 12:42:11 +010079 case 'v':
80 already_read += 1;
81 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +020082 break;
83 }
84
David Sedlákc10e7902018-12-17 02:17:59 +010085 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +020086 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +020087 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +020088 }
89
David Sedlák18730132019-03-15 15:51:34 +010090#undef IF_ARG
91#undef IF_ARG_PREFIX
92#undef IF_ARG_PREFIX_END
93
David Sedlák872c7b42018-10-26 13:15:20 +020094 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +020095}
96
David Sedlák18730132019-03-15 15:51:34 +010097/**
David Sedlákecf5eb82019-06-03 14:12:44 +020098 * @brief parse yin argument
David Sedláka7406952019-04-05 10:33:07 +020099 *
100 * @param[in] xml_ctx XML parser context.
101 * @param[in, out] data Data to read from.
102 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without special arguments).
103 * @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 +0200104 */
105static LY_ERR
David Sedlákecf5eb82019-06-03 14:12:44 +0200106yin_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 +0200107{
108 LY_ERR ret = LY_SUCCESS;
109 const char *prefix, *name;
110 size_t prefix_len, name_len;
111
112 char *buf = NULL, *out = NULL;
113 size_t buf_len = 0, out_len = 0;
114 int dynamic;
115 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
116
117 while (xml_ctx->status == LYXML_ATTRIBUTE) {
118 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
119 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
120
121 arg = match_argument_name(name, name_len);
122
David Sedlákecf5eb82019-06-03 14:12:44 +0200123 if (arg == arg_type) {
David Sedláka7406952019-04-05 10:33:07 +0200124 LY_CHECK_RET(ret);
125 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
126 LY_CHECK_RET(ret);
127 *arg_val = lydict_insert(xml_ctx->ctx, out, out_len);
128 LY_CHECK_ERR_RET(!(*arg_val), LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlákecf5eb82019-06-03 14:12:44 +0200129 } else if (arg_type == YIN_ARG_NONE) {
130 continue;
David Sedláka7406952019-04-05 10:33:07 +0200131 } else {
David Sedlákecf5eb82019-06-03 14:12:44 +0200132 /* unrecognized or unexpected attribute */
133 if (name) {
David Sedláka7406952019-04-05 10:33:07 +0200134 LOGERR(xml_ctx->ctx, LY_EDENIED, "Invalid argument in namespace element");
135 return LY_EVALID;
136 }
137 }
138 }
139
140 return LY_SUCCESS;
141}
142
143/**
David Sedlák0daba9a2019-03-22 14:07:49 +0100144 * @brief Parse content of whole element as text.
145 *
146 * @param[in] xml_ctx Xml context.
147 * @param[in] data Data to read from.
148 * @param[out] value Where content of element should be stored.
149 */
150LY_ERR
David Sedlákecf5eb82019-06-03 14:12:44 +0200151parse_text_element(struct lyxml_context *xml_ctx, const char **data, const char **value)
David Sedlák0daba9a2019-03-22 14:07:49 +0100152{
153 LY_ERR ret = LY_SUCCESS;
154 char *buf = NULL, *out = NULL;
David Sedlákecf5eb82019-06-03 14:12:44 +0200155 size_t buf_len = 0, out_len = 0;
David Sedlák0daba9a2019-03-22 14:07:49 +0100156 int dynamic;
David Sedlák0daba9a2019-03-22 14:07:49 +0100157
David Sedlákecf5eb82019-06-03 14:12:44 +0200158 ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_NONE, NULL);
David Sedláka7406952019-04-05 10:33:07 +0200159 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlák0daba9a2019-03-22 14:07:49 +0100160 LY_CHECK_RET(xml_ctx->status != LYXML_ELEM_CONTENT, LY_EVALID);
161
162 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
163 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
164 LY_CHECK_RET(ret);
165 *value = lydict_insert(xml_ctx->ctx, out, out_len);
166 LY_CHECK_ERR_RET(!(*value), LOGMEM(xml_ctx->ctx), LY_EMEM);
167 }
168
David Sedlák6b7ac2d2019-03-22 14:40:29 +0100169 return LY_SUCCESS;
David Sedlák0daba9a2019-03-22 14:07:49 +0100170}
171
David Sedláka5004e62018-12-16 23:54:47 +0100172LY_ERR
David Sedlák81e04022019-04-05 15:05:46 +0200173parse_namespace(struct lyxml_context *xml_ctx, const char **data, const char **namespace)
David Sedlák4a4c0722018-11-26 17:03:10 +0100174{
175 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100176
David Sedlákecf5eb82019-06-03 14:12:44 +0200177 ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_URI, namespace);
David Sedláka7406952019-04-05 10:33:07 +0200178 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlák4a4c0722018-11-26 17:03:10 +0100179
David Sedlákd9d3a312019-06-04 09:47:10 +0200180 return ret;
David Sedlák4a4c0722018-11-26 17:03:10 +0100181}
182
David Sedlákd5318ee2019-02-15 10:14:50 +0100183/**
184 * @brief Parse prefix statement.
185 *
186 * @param[in] xml_ctx Xml context.
187 * @param[in, out] data Data to reda from.
David Sedlák81e04022019-04-05 15:05:46 +0200188 * @param[out] prefix Where to store prefix value.
David Sedlákd5318ee2019-02-15 10:14:50 +0100189 *
190 * @return LY_ERR values.
191 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100192LY_ERR
David Sedlák81e04022019-04-05 15:05:46 +0200193parse_prefix(struct lyxml_context *xml_ctx, const char **data, const char **prefix)
David Sedlák4a4c0722018-11-26 17:03:10 +0100194{
195 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100196
David Sedlákcd0c9512019-03-29 13:23:06 +0100197 /* parse attributes */
David Sedlákecf5eb82019-06-03 14:12:44 +0200198 ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_VALUE, prefix);
David Sedlákcd0c9512019-03-29 13:23:06 +0100199 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlákecf5eb82019-06-03 14:12:44 +0200200
David Sedlákcd0c9512019-03-29 13:23:06 +0100201 return ret;
David Sedlák4a4c0722018-11-26 17:03:10 +0100202}
203
David Sedlák81e04022019-04-05 15:05:46 +0200204static LY_ERR
205yin_parse_revision_date(struct lyxml_context *xml_ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
206{
207 LY_ERR ret = LY_SUCCESS;
David Sedlákcd0c9512019-03-29 13:23:06 +0100208
David Sedlák81e04022019-04-05 15:05:46 +0200209 if (rev[0]) {
210 LOGVAL_YANG(xml_ctx, LY_VCODE_DUPSTMT, "revision-date");
211 return LY_EVALID;
212 }
213
David Sedlákecf5eb82019-06-03 14:12:44 +0200214 ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_DATE, (const char **)&rev);
David Sedlák81e04022019-04-05 15:05:46 +0200215 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlákecf5eb82019-06-03 14:12:44 +0200216 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 +0200217
David Sedlák81e04022019-04-05 15:05:46 +0200218 return ret;
219}
David Sedlákcd0c9512019-03-29 13:23:06 +0100220
David Sedlák736fd0d2019-02-15 16:06:31 +0100221static LY_ERR
David Sedlák81e04022019-04-05 15:05:46 +0200222yin_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 +0100223{
224 LY_ERR ret = LY_SUCCESS;
225 enum yang_keyword kw;
226 struct lysp_import *imp;
227 const char *prefix, *name;
228 size_t prefix_len, name_len;
229
David Sedlák81e04022019-04-05 15:05:46 +0200230 /* allocate sized array for imports */
231 LY_ARRAY_NEW_RET(xml_ctx->ctx, *imports, imp, LY_EVALID);
David Sedlák736fd0d2019-02-15 16:06:31 +0100232
David Sedláka7406952019-04-05 10:33:07 +0200233 /* parse import attributes */
David Sedlákecf5eb82019-06-03 14:12:44 +0200234 ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_MODULE, &imp->name);
David Sedlák736fd0d2019-02-15 16:06:31 +0100235 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 +0100236 kw = match_keyword(name, name_len, prefix_len);
David Sedlák736fd0d2019-02-15 16:06:31 +0100237 switch (kw) {
238 case YANG_PREFIX:
David Sedlák81e04022019-04-05 15:05:46 +0200239 LY_CHECK_ERR_RET(imp->prefix, LOGVAL_YANG(xml_ctx, LY_VCODE_DUPSTMT, "prefix"), LY_EVALID);
240 parse_prefix(xml_ctx, data, &imp->prefix);
David Sedlákcd0c9512019-03-29 13:23:06 +0100241 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100242 case YANG_DESCRIPTION:
David Sedlák81e04022019-04-05 15:05:46 +0200243 LY_CHECK_ERR_RET(imp->dsc, LOGVAL_YANG(xml_ctx, LY_VCODE_DUPSTMT, "description"), LY_EVALID);
David Sedlákecf5eb82019-06-03 14:12:44 +0200244 parse_text_element(xml_ctx, data, &imp->dsc);
David Sedlákcd0c9512019-03-29 13:23:06 +0100245 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100246 case YANG_REFERENCE:
David Sedlák81e04022019-04-05 15:05:46 +0200247 LY_CHECK_ERR_RET(imp->ref, LOGVAL_YANG(xml_ctx, LY_VCODE_DUPSTMT, "reference"), LY_EVALID);
David Sedlákecf5eb82019-06-03 14:12:44 +0200248 parse_text_element(xml_ctx, data, &imp->ref);
David Sedlákcd0c9512019-03-29 13:23:06 +0100249 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100250 case YANG_REVISION_DATE:
David Sedlákecf5eb82019-06-03 14:12:44 +0200251 yin_parse_revision_date(xml_ctx, data, imp->rev, &imp->exts);
David Sedlák3a55bc12019-06-03 08:57:29 +0200252 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100253 case YANG_CUSTOM:
254 /* TODO parse extension */
David Sedlák3a55bc12019-06-03 08:57:29 +0200255 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100256 default:
257 /* TODO log error */
258 return LY_EVALID;
259 }
260 }
261
262 /* TODO add log macro and log error */
263 LY_CHECK_RET(!imp->prefix);
264 return ret;
265}
266
David Sedlákd5318ee2019-02-15 10:14:50 +0100267/**
268 * @brief Parse module substatements.
269 *
270 * @param[in] xml_ctx xml context.
271 * @param[in, out] data Data to read from.
272 * @param[out] mod Parsed module structure
273 *
274 * @return LY_ERR values.
275 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100276LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100277parse_mod(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200278{
David Sedlákf3b24f62018-11-02 10:40:47 +0100279 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100280 enum yang_keyword kw = YANG_NONE;
David Sedláke4889912018-11-02 09:52:40 +0100281 const char *prefix, *name;
David Sedlák3b4db242018-10-19 16:11:01 +0200282 size_t prefix_len, name_len;
David Sedlák4b4713f2019-02-15 13:47:45 +0100283 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
David Sedláka7406952019-04-05 10:33:07 +0200284 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
David Sedlák3b4db242018-10-19 16:11:01 +0200285
David Sedlákf3b24f62018-11-02 10:40:47 +0100286 char *buf = NULL, *out = NULL;
287 size_t buf_len = 0, out_len = 0;
288 int dynamic;
289
David Sedlák18730132019-03-15 15:51:34 +0100290 /* parse module attributes */
291 while (xml_ctx->status == LYXML_ATTRIBUTE) {
292 ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
293 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
294
295 arg = match_argument_name(name, name_len);
296
297 switch (arg) {
David Sedlák18730132019-03-15 15:51:34 +0100298 case YIN_ARG_NAME:
299 /* check for multiple definitions of name */
300 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);
301
302 /* read module name */
303 if (xml_ctx->status != LYXML_ATTR_CONTENT) {
304 LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Missing value of argument \"name\".");
305 }
306 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
307 LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
308 (*mod)->mod->name = lydict_insert(xml_ctx->ctx, out, out_len);
309 LY_CHECK_ERR_RET(!(*mod)->mod->name, LOGMEM(xml_ctx->ctx), LY_EMEM);
310 break;
David Sedlákecf5eb82019-06-03 14:12:44 +0200311
David Sedlák18730132019-03-15 15:51:34 +0100312 default:
David Sedlákecf5eb82019-06-03 14:12:44 +0200313 /* unrecognized attribute */
314 /* unrecognized or unexpected attribute */
315 /* TODO probably still can be from extension */
316 if (arg != YIN_ARG_UNKNOWN || name) {
David Sedlák18730132019-03-15 15:51:34 +0100317 LOGERR(xml_ctx->ctx, LY_EDENIED, "Invalid argument in module element");
318 return LY_EVALID;
319 }
David Sedlákecf5eb82019-06-03 14:12:44 +0200320
David Sedlák18730132019-03-15 15:51:34 +0100321 break;
322 }
David Sedlák3b4db242018-10-19 16:11:01 +0200323 }
324
David Sedlák18730132019-03-15 15:51:34 +0100325 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 +0100326
David Sedlákc136b972019-03-08 13:39:06 +0100327 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák18730132019-03-15 15:51:34 +0100328 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 +0100329
David Sedlák736fd0d2019-02-15 16:06:31 +0100330 /* loop over all elements and parse them */
David Sedlákc136b972019-03-08 13:39:06 +0100331 while (xml_ctx->status != LYXML_END) {
David Sedlák4b4713f2019-02-15 13:47:45 +0100332/* TODO ADD error log to macro */
333#define CHECK_ORDER(SECTION) \
334 if (mod_stmt > SECTION) {return LY_EVALID;}mod_stmt = SECTION
335
336 switch (kw) {
337 /* module header */
338 case YANG_NAMESPACE:
339 case YANG_PREFIX:
340 CHECK_ORDER(Y_MOD_MODULE_HEADER);
341 break;
342 case YANG_YANG_VERSION:
343 CHECK_ORDER(Y_MOD_MODULE_HEADER);
344 break;
345 /* linkage */
346 case YANG_INCLUDE:
347 case YANG_IMPORT:
348 CHECK_ORDER(Y_MOD_LINKAGE);
349 break;
350 /* meta */
351 case YANG_ORGANIZATION:
352 case YANG_CONTACT:
353 case YANG_DESCRIPTION:
354 case YANG_REFERENCE:
355 CHECK_ORDER(Y_MOD_META);
356 break;
357
358 /* revision */
359 case YANG_REVISION:
360 CHECK_ORDER(Y_MOD_REVISION);
361 break;
362 /* body */
363 case YANG_ANYDATA:
364 case YANG_ANYXML:
365 case YANG_AUGMENT:
366 case YANG_CHOICE:
367 case YANG_CONTAINER:
368 case YANG_DEVIATION:
369 case YANG_EXTENSION:
370 case YANG_FEATURE:
371 case YANG_GROUPING:
372 case YANG_IDENTITY:
373 case YANG_LEAF:
374 case YANG_LEAF_LIST:
375 case YANG_LIST:
376 case YANG_NOTIFICATION:
377 case YANG_RPC:
378 case YANG_TYPEDEF:
379 case YANG_USES:
380 case YANG_CUSTOM:
381 mod_stmt = Y_MOD_BODY;
382 break;
383 default:
384 /* error will be handled in the next switch */
385 break;
386 }
387#undef CHECK_ORDER
388
David Sedlák4a4c0722018-11-26 17:03:10 +0100389 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákc136b972019-03-08 13:39:06 +0100390 LY_CHECK_RET(ret != LY_SUCCESS, LY_EMEM);
David Sedlák4a4c0722018-11-26 17:03:10 +0100391
David Sedlákc136b972019-03-08 13:39:06 +0100392 if (name) {
David Sedlák18730132019-03-15 15:51:34 +0100393 kw = match_keyword(name, name_len, prefix_len);
David Sedlákc136b972019-03-08 13:39:06 +0100394 switch (kw) {
David Sedlák736fd0d2019-02-15 16:06:31 +0100395
David Sedlákc136b972019-03-08 13:39:06 +0100396 /* module header */
397 case YANG_NAMESPACE:
David Sedlák81e04022019-04-05 15:05:46 +0200398 LY_CHECK_RET(parse_namespace(xml_ctx, data, &(*mod)->mod->ns));
David Sedlákc136b972019-03-08 13:39:06 +0100399 break;
400 case YANG_PREFIX:
David Sedlák81e04022019-04-05 15:05:46 +0200401 LY_CHECK_RET(parse_prefix(xml_ctx, data, &(*mod)->mod->prefix));
David Sedlákc136b972019-03-08 13:39:06 +0100402 break;
David Sedlák4a4c0722018-11-26 17:03:10 +0100403
David Sedlákc136b972019-03-08 13:39:06 +0100404 /* linkage */
405 case YANG_IMPORT:
David Sedlák81e04022019-04-05 15:05:46 +0200406 yin_parse_import(xml_ctx, (*mod)->mod->prefix, data, &(*mod)->imports);
David Sedlákc136b972019-03-08 13:39:06 +0100407 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100408
David Sedlákc136b972019-03-08 13:39:06 +0100409 /* meta */
410 case YANG_ORGANIZATION:
David Sedlákecf5eb82019-06-03 14:12:44 +0200411 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->org));
David Sedlákc136b972019-03-08 13:39:06 +0100412 break;
413 case YANG_CONTACT:
David Sedlákecf5eb82019-06-03 14:12:44 +0200414 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->contact));
David Sedlákc136b972019-03-08 13:39:06 +0100415 break;
416 case YANG_DESCRIPTION:
David Sedlákecf5eb82019-06-03 14:12:44 +0200417 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->dsc));
David Sedlákc136b972019-03-08 13:39:06 +0100418 break;
419 case YANG_REFERENCE:
David Sedlákecf5eb82019-06-03 14:12:44 +0200420 LY_CHECK_RET(parse_text_element(xml_ctx, data, &(*mod)->mod->ref));
David Sedlákc136b972019-03-08 13:39:06 +0100421 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100422
David Sedlákc136b972019-03-08 13:39:06 +0100423 default:
David Sedlák18730132019-03-15 15:51:34 +0100424 return LY_EVALID;
David Sedlákc136b972019-03-08 13:39:06 +0100425 break;
426 }
David Sedlák4a4c0722018-11-26 17:03:10 +0100427 }
428 }
429
David Sedlákf3b24f62018-11-02 10:40:47 +0100430 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200431}
432
David Sedlákd5318ee2019-02-15 10:14:50 +0100433/**
434 * @brief Parse yin submodule.
435 *
436 * @param[in] ctx Context of YANG schemas.
437 * @param[in] data Data to read from.
438 * @param[out] submod Module to write to.
439 *
440 * @return LY_ERR values.
441 */
442LY_ERR
443yin_parse_submodule(struct ly_ctx *ctx, const char *data, struct lysp_submodule **submod)
444{
445 LY_ERR ret = LY_SUCCESS;
446 enum yang_keyword kw = YANG_NONE;
447 struct lyxml_context xml_ctx;
448 struct lysp_submodule *mod_p = NULL;
449 const char *prefix, *name;
450 size_t prefix_len, name_len;
David Sedlák3017da42019-02-15 09:48:04 +0100451
David Sedlákd5318ee2019-02-15 10:14:50 +0100452 /* initialize xml context */
453 memset(&xml_ctx, 0, sizeof xml_ctx);
454 xml_ctx.ctx = ctx;
455 xml_ctx.line = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100456
David Sedlákd5318ee2019-02-15 10:14:50 +0100457 /* check submodule */
458 ret = lyxml_get_element(&xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
459 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák18730132019-03-15 15:51:34 +0100460 kw = match_keyword(name, name_len, prefix_len);
David Sedlákd5318ee2019-02-15 10:14:50 +0100461 if (kw == YANG_MODULE) {
462 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
463 ret = LY_EINVAL;
464 goto cleanup;
465 } else if (kw != YANG_SUBMODULE) {
David Sedlák0a875b42019-03-07 22:24:05 +0100466 LOGVAL_YANG(&xml_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
467 ly_stmt2str(kw));
David Sedlákd5318ee2019-02-15 10:14:50 +0100468 ret = LY_EVALID;
469 goto cleanup;
470 }
David Sedlák3017da42019-02-15 09:48:04 +0100471
David Sedlákd5318ee2019-02-15 10:14:50 +0100472 /* allocate module */
473 mod_p = calloc(1, sizeof *mod_p);
474 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
475 mod_p->parsing = 1;
David Sedlák3017da42019-02-15 09:48:04 +0100476
David Sedlákd5318ee2019-02-15 10:14:50 +0100477 /* parser submodule substatements */
478 //ret = parse_submod(&xml_ctx, &data, mod_p);
479 LY_CHECK_GOTO(ret, cleanup);
David Sedlák3017da42019-02-15 09:48:04 +0100480
David Sedlákd5318ee2019-02-15 10:14:50 +0100481 mod_p->parsing = 0;
482 *submod = mod_p;
David Sedlák3017da42019-02-15 09:48:04 +0100483
David Sedlákd5318ee2019-02-15 10:14:50 +0100484cleanup:
485 if (ret) {
486 lysp_submodule_free(ctx, mod_p);
487 }
David Sedlák3017da42019-02-15 09:48:04 +0100488
David Sedlákd5318ee2019-02-15 10:14:50 +0100489 lyxml_context_clear(&xml_ctx);
490 return ret;
491}
David Sedlák3017da42019-02-15 09:48:04 +0100492
David Sedlákd5318ee2019-02-15 10:14:50 +0100493/**
494 * @brief Parse yin module.
495 *
496 * @param[in] ctx Context of YANG schemas.
497 * @param[in] data Data to read from.
498 * @param[out] mod Module to write to.
499 *
500 * @return LY_ERR values.
501 */
David Sedlák3b4db242018-10-19 16:11:01 +0200502LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100503yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200504{
David Sedláke4889912018-11-02 09:52:40 +0100505 LY_ERR ret = LY_SUCCESS;
506 enum yang_keyword kw = YANG_NONE;
David Sedlákecf5eb82019-06-03 14:12:44 +0200507 struct lys_parser_ctx parser_ctx;
David Sedlákaadab9c2019-04-05 15:01:27 +0200508 struct lyxml_context *xml_ctx = (struct lyxml_context *)&parser_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ákaadab9c2019-04-05 15:01:27 +0200514 memset(&parser_ctx, 0, sizeof parser_ctx);
515 xml_ctx->ctx = ctx;
516 xml_ctx->line = 1;
David Sedláke4889912018-11-02 09:52:40 +0100517
David Sedlák3017da42019-02-15 09:48:04 +0100518 /* check submodule */
David Sedlákaadab9c2019-04-05 15:01:27 +0200519 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ák18730132019-03-15 15:51:34 +0100521 kw = match_keyword(name, name_len, prefix_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) {
David Sedlákaadab9c2019-04-05 15:01:27 +0200527 LOGVAL_YANG(xml_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
David Sedlák0a875b42019-03-07 22:24:05 +0100528 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +0100529 ret = LY_EVALID;
530 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +0100531 }
532
David Sedlák3017da42019-02-15 09:48:04 +0100533 /* allocate module */
534 mod_p = calloc(1, sizeof *mod_p);
535 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
536 mod_p->mod = mod;
537 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +0100538
David Sedlák3017da42019-02-15 09:48:04 +0100539 /* parser module substatements */
David Sedlákaadab9c2019-04-05 15:01:27 +0200540 ret = parse_mod(xml_ctx, &data, &mod_p);
David Sedlák3017da42019-02-15 09:48:04 +0100541 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +0100542
David Sedlák3017da42019-02-15 09:48:04 +0100543 mod_p->parsing = 0;
544 mod->parsed = mod_p;
545
546cleanup:
547 if (ret) {
548 lysp_module_free(mod_p);
549 }
550
David Sedlákaadab9c2019-04-05 15:01:27 +0200551 lyxml_context_clear(xml_ctx);
David Sedlák2e411422018-12-17 02:35:39 +0100552 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200553}