blob: b421657708ef96c898ffc1070e4dcd2c53358562 [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 *
David Sedlákb1ce3f82019-06-05 14:37:26 +02006 * Copyright (c) 2015 - 2019 CESNET, z.s.p.o.
David Sedlák3b4db242018-10-19 16:11:01 +02007 *
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ák3ffbc522019-07-02 17:49:28 +020016#include <assert.h>
David Sedlák3b4db242018-10-19 16:11:01 +020017#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
David Sedlák872c7b42018-10-26 13:15:20 +020020#include <string.h>
David Sedlákd6e56892019-07-01 15:40:24 +020021#include <stdbool.h>
David Sedlákf824ad52018-10-14 23:58:15 +020022
David Sedlákf824ad52018-10-14 23:58:15 +020023#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020024#include "dict.h"
David Sedlák3b4db242018-10-19 16:11:01 +020025#include "xml.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020026#include "tree.h"
27#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020028#include "tree_schema_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020029#include "parser_yin.h"
David Sedlák00250342019-06-21 14:19:39 +020030
David Sedlák2b214ac2019-06-06 16:11:03 +020031/**
32 * @brief check if given string is URI of yin namespace.
33 * @param ns Namespace URI to check.
34 *
35 * @return true if ns equals YIN_NS_URI false otherwise.
36 */
37#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
38
David Sedlákf6251182019-06-06 10:22:13 +020039const char *const yin_attr_list[] = {
40 [YIN_ARG_NAME] = "name",
41 [YIN_ARG_TARGET_NODE] = "target-node",
42 [YIN_ARG_MODULE] = "module",
43 [YIN_ARG_VALUE] = "value",
44 [YIN_ARG_TEXT] = "text",
45 [YIN_ARG_CONDITION] = "condition",
46 [YIN_ARG_URI] = "uri",
47 [YIN_ARG_DATE] = "date",
48 [YIN_ARG_TAG] = "tag",
49 [YIN_ARG_XMLNS] = "xmlns",
50};
51
David Sedlák1bccdfa2019-06-17 15:55:27 +020052enum yang_keyword
David Sedlák8f7a1172019-06-20 14:42:18 +020053yin_match_keyword(struct lyxml_context *xml_ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len)
David Sedlák1bccdfa2019-06-17 15:55:27 +020054{
David Sedlák8f7a1172019-06-20 14:42:18 +020055 const char *start = NULL;
56 enum yang_keyword kw = YANG_NONE;
57 const struct lyxml_ns *ns = NULL;
58
59 if (!name || name_len == 0) {
David Sedlák1bccdfa2019-06-17 15:55:27 +020060 return YANG_NONE;
61 }
62
David Sedlák8f7a1172019-06-20 14:42:18 +020063 ns = lyxml_ns_get(xml_ctx, prefix, prefix_len);
64 if (ns) {
65 if (!IS_YIN_NS(ns->uri)) {
66 return YANG_CUSTOM;
67 }
68 } else {
69 /* elements without namespace are automatically unknown */
70 return YANG_NONE;
71 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020072
David Sedlák8f7a1172019-06-20 14:42:18 +020073
74 start = name;
75 kw = lysp_match_kw(NULL, &name);
76
77 if (name - start == (long int)name_len) {
David Sedlák1bccdfa2019-06-17 15:55:27 +020078 return kw;
79 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020080 if (strncmp(start, "text", name_len) == 0) {
81 return YIN_TEXT;
82 } else if (strncmp(start, "value", name_len) == 0) {
83 return YIN_VALUE;
84 } else {
85 return YANG_NONE;
86 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020087 }
88}
89
David Sedlák872c7b42018-10-26 13:15:20 +020090enum YIN_ARGUMENT
David Sedlák060b00e2019-06-19 11:12:06 +020091yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020092{
David Sedláka7406952019-04-05 10:33:07 +020093 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +020094 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +020095 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +020096
David Sedlák94de2aa2019-02-15 12:42:11 +010097#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
98#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +010099#define IF_ARG_PREFIX_END }
100
David Sedlák1c8b2702019-02-22 11:03:02 +0100101 switch (*name) {
David Sedlák18730132019-03-15 15:51:34 +0100102 case 'x':
103 already_read += 1;
104 IF_ARG("mlns", 4, YIN_ARG_XMLNS);
105 break;
David Sedlák94de2aa2019-02-15 12:42:11 +0100106 case 'c':
107 already_read += 1;
108 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
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 'd':
112 already_read += 1;
113 IF_ARG("ate", 3, YIN_ARG_DATE);
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 'm':
117 already_read += 1;
118 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200119 break;
120
David Sedlák94de2aa2019-02-15 12:42:11 +0100121 case 'n':
122 already_read += 1;
123 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200124 break;
125
David Sedlák94de2aa2019-02-15 12:42:11 +0100126 case 't':
127 already_read += 1;
128 IF_ARG_PREFIX("a", 1)
129 IF_ARG("g", 1, YIN_ARG_TAG)
130 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
131 IF_ARG_PREFIX_END
132 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200133 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200134
David Sedlák94de2aa2019-02-15 12:42:11 +0100135 case 'u':
136 already_read += 1;
137 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200138 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200139
David Sedlák94de2aa2019-02-15 12:42:11 +0100140 case 'v':
141 already_read += 1;
142 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200143 break;
144 }
145
David Sedlákc10e7902018-12-17 02:17:59 +0100146 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200147 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200148 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200149 }
150
David Sedlák18730132019-03-15 15:51:34 +0100151#undef IF_ARG
152#undef IF_ARG_PREFIX
153#undef IF_ARG_PREFIX_END
154
David Sedlák872c7b42018-10-26 13:15:20 +0200155 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200156}
157
David Sedlák00250342019-06-21 14:19:39 +0200158static void free_arg_rec(struct lyxml_context *xml_ctx, struct yin_arg_record *record) {
159 (void)xml_ctx; /* unused */
160 if (record->dynamic_content) {
161 free(record->content);
162 }
163}
164
David Sedlák8f7a1172019-06-20 14:42:18 +0200165LY_ERR
166yin_load_attributes(struct lyxml_context *xml_ctx, const char **data, struct yin_arg_record **args)
David Sedláka7406952019-04-05 10:33:07 +0200167{
168 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200169 struct yin_arg_record *argument_record = NULL;
David Sedláka7406952019-04-05 10:33:07 +0200170
David Sedlák7ff55a92019-06-17 11:11:41 +0200171 /* load all attributes first */
David Sedlák57715b12019-06-17 13:05:22 +0200172 while (xml_ctx->status == LYXML_ATTRIBUTE) {
David Sedlák8f7a1172019-06-20 14:42:18 +0200173 LY_ARRAY_NEW_GOTO(xml_ctx->ctx, *args, argument_record, ret, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200174 ret = lyxml_get_attribute(xml_ctx, data, &argument_record->prefix, &argument_record->prefix_len,
175 &argument_record->name, &argument_record->name_len);
David Sedlák00250342019-06-21 14:19:39 +0200176 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200177
David Sedlák7ff55a92019-06-17 11:11:41 +0200178 if (xml_ctx->status == LYXML_ATTR_CONTENT) {
David Sedlák57715b12019-06-17 13:05:22 +0200179 argument_record->content = NULL;
180 argument_record->content_len = 0;
181 argument_record->dynamic_content = 0;
182 ret = lyxml_get_string(xml_ctx, data, &argument_record->content, &argument_record->content_len,
183 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák00250342019-06-21 14:19:39 +0200184 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200185 }
186 }
187
David Sedlák8f7a1172019-06-20 14:42:18 +0200188cleanup:
189 if (ret != LY_SUCCESS) {
David Sedlák00250342019-06-21 14:19:39 +0200190 FREE_ARRAY(xml_ctx, *args, free_arg_rec);
191 *args = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200192 }
193 return ret;
194}
195
196LY_ERR
197yin_parse_attribute(struct lyxml_context *xml_ctx, struct yin_arg_record **args, enum YIN_ARGUMENT arg_type, const char **arg_val)
198{
199 LY_ERR ret = LY_SUCCESS;
200 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
201 struct yin_arg_record *iter = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200202
David Sedlák1bccdfa2019-06-17 15:55:27 +0200203 /* validation of attributes */
David Sedlák8f7a1172019-06-20 14:42:18 +0200204 LY_ARRAY_FOR(*args, struct yin_arg_record, iter) {
David Sedlák00250342019-06-21 14:19:39 +0200205 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
206 if (!iter->prefix) {
David Sedlák060b00e2019-06-19 11:12:06 +0200207 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200208 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200209 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200210 } else if (arg == arg_type) {
David Sedlák57715b12019-06-17 13:05:22 +0200211 if (iter->dynamic_content) {
212 *arg_val = lydict_insert_zc(xml_ctx->ctx, iter->content);
David Sedlák00250342019-06-21 14:19:39 +0200213 LY_CHECK_ERR_GOTO(!(*arg_val), LOGMEM(xml_ctx->ctx); ret = LY_EMEM, cleanup);
214 /* string is no longer supposed to be freed when the sized array is freed */
215 iter->dynamic_content = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200216 } else {
217 *arg_val = lydict_insert(xml_ctx->ctx, iter->content, iter->content_len);
218 LY_CHECK_ERR_GOTO(!(*arg_val), LOGMEM(xml_ctx->ctx); ret = LY_EMEM, cleanup);
219 }
David Sedlák2b214ac2019-06-06 16:11:03 +0200220 } else {
David Sedlák7ff55a92019-06-17 11:11:41 +0200221 LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected attribute \"%.*s\".", iter->name_len, iter->name);
222 ret = LY_EVALID;
223 goto cleanup;
David Sedláka7406952019-04-05 10:33:07 +0200224 }
225 }
226 }
227
David Sedlák7ff55a92019-06-17 11:11:41 +0200228cleanup:
David Sedlák7ff55a92019-06-17 11:11:41 +0200229 return ret;
David Sedláka7406952019-04-05 10:33:07 +0200230}
231
David Sedlákd6e56892019-07-01 15:40:24 +0200232/**
233 * @brief get record with given type.
234 *
235 * @param[in] type Type of wanted record.
236 * @param[in] array_size Size of array.
237 * @param[in] array Searched array.
238 *
239 * @return Pointer to desired record on success, NULL if element is not in the array.
240 */
241struct yin_subelement *
242get_record(enum yang_keyword type, size_t array_size, struct yin_subelement *array)
243{
244 for (size_t i = 0; i < array_size; ++i) {
245 if (array[i].type == type) {
246 return &array[i];
247 }
248 }
249
250 return NULL;
251}
252
253/**
David Sedlák3ffbc522019-07-02 17:49:28 +0200254 * @brief Generic function for content parsing
David Sedlákd6e56892019-07-01 15:40:24 +0200255 *
256 * @param[in,out] xml_ctx Xml context.
David Sedlák3ffbc522019-07-02 17:49:28 +0200257 * @param[in] subelem_info array of valid subelement types and meta information,
258 * array must be ordered by subelem_info->type in ascending order.
David Sedlákd6e56892019-07-01 15:40:24 +0200259 * @param[in] subelem_info_size Size of subelem_info array.
David Sedlákd6e56892019-07-01 15:40:24 +0200260 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák3ffbc522019-07-02 17:49:28 +0200261 * @param[in] current_element Type of current element.
262 * @param[out] Where the text content of element should be stored. Text content is ignored if set to NULL.
263 * @param[in] exts Extension instance to add to. Can be null if element cannot have extension as subelement.
David Sedlákd6e56892019-07-01 15:40:24 +0200264 * @return LY_ERR values.
265 */
266LY_ERR
David Sedlák3ffbc522019-07-02 17:49:28 +0200267yin_parse_content(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
268 const char **data, enum yang_keyword current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +0200269{
270 LY_ERR ret = LY_SUCCESS;
271 struct sized_string prefix, name;
272 char *out;
273 size_t out_len;
274 int dynamic;
David Sedlák3ffbc522019-07-02 17:49:28 +0200275 struct yin_arg_record *subelem_attrs = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +0200276 enum yang_keyword kw = YANG_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +0200277 struct yin_subelement *subelem_info_rec = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +0200278
279 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
280 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
281 /* current element has subelements as content */
282 if (ret == LY_EINVAL) {
283 while (xml_ctx->status == LYXML_ELEMENT) {
284 ret = lyxml_get_element(xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len);
285 LY_CHECK_GOTO(ret, cleanup);
286 if (!name.value) {
287 /* end of current element reached */
288 break;
289 }
290 ret = yin_load_attributes(xml_ctx, data, &subelem_attrs);
291 LY_CHECK_GOTO(ret, cleanup);
292 kw = yin_match_keyword(xml_ctx, name.value, name.len, prefix.value, prefix.len);
293
294 /* check if this element can be child of current element */
David Sedlák3ffbc522019-07-02 17:49:28 +0200295 subelem_info_rec = get_record(kw, subelem_info_size, subelem_info);
296 if (!subelem_info_rec) {
David Sedlákd6e56892019-07-01 15:40:24 +0200297 LOGVAL_PARSER(xml_ctx, LY_VCODE_UNEXP_SUBELEM, name.len, name.value, ly_stmt2str(current_element));
298 ret = LY_EVALID;
299 goto cleanup;
300 }
301
302 /* TODO macro to check order */
David Sedlák3ffbc522019-07-02 17:49:28 +0200303 /* TODO flag check */
David Sedlákd6e56892019-07-01 15:40:24 +0200304 switch (kw) {
305 case YANG_CUSTOM:
David Sedlák3ffbc522019-07-02 17:49:28 +0200306 ret = yin_parse_extension_instance(xml_ctx, &subelem_attrs, data, name2fullname(name.value, prefix.len),
307 namelen2fulllen(name.len, prefix.len),
308 (struct yin_ext_meta *)subelem_info_rec->dest, exts);
309 LY_CHECK_GOTO(ret, cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +0200310 break;
311 case YANG_ACTION:
312 break;
313 case YANG_ANYDATA:
314 break;
315 case YANG_ANYXML:
316 break;
317 case YANG_ARGUMENT:
David Sedlák3ffbc522019-07-02 17:49:28 +0200318 ret = yin_parse_argument_element(xml_ctx, &subelem_attrs, data, (struct yin_argument_meta *)subelem_info_rec->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +0200319 break;
320 case YANG_AUGMENT:
321 break;
322 case YANG_BASE:
323 break;
324 case YANG_BELONGS_TO:
325 break;
326 case YANG_BIT:
327 break;
328 case YANG_CASE:
329 break;
330 case YANG_CHOICE:
331 break;
332 case YANG_CONFIG:
333 break;
334 case YANG_CONTACT:
335 break;
336 case YANG_CONTAINER:
337 break;
338 case YANG_DEFAULT:
339 break;
340 case YANG_DESCRIPTION:
David Sedlák3ffbc522019-07-02 17:49:28 +0200341 ret = yin_parse_meta_element(xml_ctx, data, YANG_DESCRIPTION, (const char **)subelem_info_rec->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +0200342 break;
343 case YANG_DEVIATE:
344 break;
345 case YANG_DEVIATION:
346 break;
347 case YANG_ENUM:
348 break;
349 case YANG_ERROR_APP_TAG:
350 break;
351 case YANG_ERROR_MESSAGE:
352 break;
353 case YANG_EXTENSION:
354 break;
355 case YANG_FEATURE:
356 break;
357 case YANG_FRACTION_DIGITS:
358 break;
359 case YANG_GROUPING:
360 break;
361 case YANG_IDENTITY:
362 break;
363 case YANG_IF_FEATURE:
364 break;
365 case YANG_IMPORT:
366 break;
367 case YANG_INCLUDE:
368 break;
369 case YANG_INPUT:
370 break;
371 case YANG_KEY:
372 break;
373 case YANG_LEAF:
374 break;
375 case YANG_LEAF_LIST:
376 break;
377 case YANG_LENGTH:
378 break;
379 case YANG_LIST:
380 break;
381 case YANG_MANDATORY:
382 break;
383 case YANG_MAX_ELEMENTS:
384 break;
385 case YANG_MIN_ELEMENTS:
386 break;
387 case YANG_MODIFIER:
388 break;
389 case YANG_MODULE:
390 break;
391 case YANG_MUST:
392 break;
393 case YANG_NAMESPACE:
394 break;
395 case YANG_NOTIFICATION:
396 break;
397 case YANG_ORDERED_BY:
398 break;
399 case YANG_ORGANIZATION:
400 break;
401 case YANG_OUTPUT:
402 break;
403 case YANG_PATH:
404 break;
405 case YANG_PATTERN:
406 break;
407 case YANG_POSITION:
408 break;
409 case YANG_PREFIX:
David Sedlák3ffbc522019-07-02 17:49:28 +0200410 ret = yin_parse_prefix(xml_ctx, subelem_attrs, (const char **)subelem_info_rec->dest, data, exts);
David Sedlákd6e56892019-07-01 15:40:24 +0200411 break;
412 case YANG_PRESENCE:
413 break;
414 case YANG_RANGE:
415 break;
416 case YANG_REFERENCE:
David Sedlák3ffbc522019-07-02 17:49:28 +0200417 ret = yin_parse_meta_element(xml_ctx, data, YANG_REFERENCE, (const char **)subelem_info_rec->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +0200418 break;
419 case YANG_REFINE:
420 break;
421 case YANG_REQUIRE_INSTANCE:
422 break;
423 case YANG_REVISION:
424 break;
425 case YANG_REVISION_DATE:
David Sedlák3ffbc522019-07-02 17:49:28 +0200426 ret = yin_parse_revision_date(xml_ctx, &subelem_attrs, data, (char *)subelem_info_rec->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +0200427 break;
428 case YANG_RPC:
429 break;
430 case YANG_STATUS:
David Sedlák3ffbc522019-07-02 17:49:28 +0200431 ret = yin_parse_status(xml_ctx, &subelem_attrs, data, (uint16_t *)subelem_info_rec->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +0200432 break;
433 case YANG_SUBMODULE:
434 break;
435 case YANG_TYPE:
436 break;
437 case YANG_TYPEDEF:
438 break;
439 case YANG_UNIQUE:
440 break;
441 case YANG_UNITS:
442 break;
443 case YANG_USES:
444 break;
445 case YANG_VALUE:
446 break;
447 case YANG_WHEN:
448 break;
449 case YANG_YANG_VERSION:
450 break;
451 case YANG_YIN_ELEMENT:
David Sedlák3ffbc522019-07-02 17:49:28 +0200452 ret = yin_parse_yin_element_element(xml_ctx, subelem_attrs, data, (uint16_t *)subelem_info_rec->dest, exts);
453 break;
454 case YIN_TEXT:
455 ret = yin_parse_text_element(xml_ctx, data, (const char **)subelem_info_rec->dest);
456 break;
457 case YIN_VALUE:
David Sedlákd6e56892019-07-01 15:40:24 +0200458 break;
459 default:
David Sedlák3ffbc522019-07-02 17:49:28 +0200460 /* TODO special cases */
David Sedlákd6e56892019-07-01 15:40:24 +0200461 break;
462 }
David Sedlák3ffbc522019-07-02 17:49:28 +0200463 LY_CHECK_GOTO(ret, cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +0200464 FREE_ARRAY(xml_ctx, subelem_attrs, free_arg_rec);
465 subelem_attrs = NULL;
David Sedlák3ffbc522019-07-02 17:49:28 +0200466 subelem_info_rec = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +0200467 }
468 } else {
469 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +0200470 /* save text content, if text_content isn't set, it's just ignored */
471 if (text_content) {
472 if (dynamic) {
473 *text_content = lydict_insert_zc(xml_ctx->ctx, out);
474 if (!*text_content) {
475 free(out);
476 return LY_EMEM;
477 }
478 } else {
479 if (out_len == 0) {
480 *text_content = NULL;
481 } else {
482 *text_content = lydict_insert(xml_ctx->ctx, out, out_len);
483 }
484 }
485 }
David Sedlákd6e56892019-07-01 15:40:24 +0200486 /* load closing element */
487 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len));
488 }
489 }
490
491cleanup:
492 FREE_ARRAY(xml_ctx, subelem_attrs, free_arg_rec);
493 return ret;
494}
495
David Sedlák0daba9a2019-03-22 14:07:49 +0100496LY_ERR
David Sedlák3ffbc522019-07-02 17:49:28 +0200497yin_parse_text_element(struct lyxml_context *xml_ctx, const char **data, const char **value)
David Sedlák0daba9a2019-03-22 14:07:49 +0100498{
499 LY_ERR ret = LY_SUCCESS;
David Sedlák0daba9a2019-03-22 14:07:49 +0100500
David Sedlák3ffbc522019-07-02 17:49:28 +0200501 ret = yin_parse_content(xml_ctx, NULL, 0, data, YIN_TEXT, value, NULL);
David Sedlák0daba9a2019-03-22 14:07:49 +0100502
David Sedlák00250342019-06-21 14:19:39 +0200503 return ret;
David Sedlák15a92662019-06-18 11:55:15 +0200504}
505
David Sedlák00250342019-06-21 14:19:39 +0200506/**
David Sedlák3ffbc522019-07-02 17:49:28 +0200507 * @brief map keyword type to substatement info.
508 *
509 * @param[in] kw Keyword type.
510 * @param[out] sub Substatement info.
511 *
512 * @return LY_SUCCESS on success LY_EINVAL if kw can't be mapped.
513 */
514LY_ERR
515kw2lyext_substmt(enum yang_keyword kw, LYEXT_SUBSTMT *sub)
516{
517 switch (kw) {
518 case YANG_ORGANIZATION:
519 *sub = LYEXT_SUBSTMT_ORGANIZATION;
520 return LY_SUCCESS;
521 case YANG_CONTACT:
522 *sub = LYEXT_SUBSTMT_CONTACT;
523 return LY_SUCCESS;
524 case YANG_DESCRIPTION:
525 *sub = LYEXT_SUBSTMT_DESCRIPTION;
526 return LY_SUCCESS;
527 case YANG_REFERENCE:
528 *sub = LYEXT_SUBSTMT_REFERENCE;
529 return LY_SUCCESS;
530
531 default:
532 return LY_EINVAL;
533 }
534}
535
536/**
David Sedlák00250342019-06-21 14:19:39 +0200537 * @brief function to parse meta tags eg. elements with text element as child
538 *
539 * @param[in] xml_ctx Xml context.
David Sedlák3ffbc522019-07-02 17:49:28 +0200540 * @param[in] args Sized array of arguments of current element.
David Sedlák00250342019-06-21 14:19:39 +0200541 * @param[in,out] data Data to read from.
542 * @param[out] value Where the content of meta tag should be stored.
543 *
544 * @return LY_ERR values.
545 */
David Sedlák15a92662019-06-18 11:55:15 +0200546LY_ERR
David Sedlák3ffbc522019-07-02 17:49:28 +0200547yin_parse_meta_element(struct lyxml_context *xml_ctx, const char **data, enum yang_keyword elem_type,
548 const char **value, struct lysp_ext_instance **exts)
David Sedlák15a92662019-06-18 11:55:15 +0200549{
David Sedlák3ffbc522019-07-02 17:49:28 +0200550 assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
551 struct yin_ext_meta ext_info = {.subelem_index = 0};
552 struct yin_subelement subelems[2] = {{YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
553 {YANG_CUSTOM, &ext_info, 0}};
554 /* set correct insubstmt info */
555 LY_CHECK_RET(kw2lyext_substmt(elem_type, &ext_info.subelem))
David Sedlák15a92662019-06-18 11:55:15 +0200556
David Sedlák3ffbc522019-07-02 17:49:28 +0200557 return yin_parse_content(xml_ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlák0daba9a2019-03-22 14:07:49 +0100558}
559
David Sedlák3ffbc522019-07-02 17:49:28 +0200560LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200561yin_parse_revision_date(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data, char *rev, struct lysp_ext_instance **exts)
David Sedlák81e04022019-04-05 15:05:46 +0200562{
563 LY_ERR ret = LY_SUCCESS;
David Sedlák3ffbc522019-07-02 17:49:28 +0200564 const char *temp_rev;
565 struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_REVISIONDATE, 0};
566 struct yin_subelement subelems[1] = {{YANG_CUSTOM, &ext_info, 0}};
David Sedlák81e04022019-04-05 15:05:46 +0200567
David Sedlák8f7a1172019-06-20 14:42:18 +0200568 LY_CHECK_RET(yin_parse_attribute(xml_ctx, args, YIN_ARG_DATE, &temp_rev))
David Sedlák81e04022019-04-05 15:05:46 +0200569 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlákda63c082019-06-04 13:52:23 +0200570 LY_CHECK_RET(lysp_check_date((struct lys_parser_ctx *)xml_ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS, LY_EVALID);
571
572 strcpy(rev, temp_rev);
573 lydict_remove(xml_ctx->ctx, temp_rev);
David Sedlák81e04022019-04-05 15:05:46 +0200574
David Sedlák3ffbc522019-07-02 17:49:28 +0200575 return yin_parse_content(xml_ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
576}
David Sedlák00250342019-06-21 14:19:39 +0200577
David Sedlák3ffbc522019-07-02 17:49:28 +0200578LY_ERR
579yin_parse_prefix(struct lyxml_context *xml_ctx, struct yin_arg_record *attrs, const char **prefix, const char **data, struct lysp_ext_instance **exts)
580{
581 struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_PREFIX, 0};
582 struct yin_subelement subelems[1] = {{YANG_CUSTOM, &ext_info, 0}};
583 LY_CHECK_RET(yin_parse_attribute(xml_ctx, &attrs, YIN_ARG_VALUE, prefix));
David Sedlák00250342019-06-21 14:19:39 +0200584
David Sedlák3ffbc522019-07-02 17:49:28 +0200585 return yin_parse_content(xml_ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
David Sedlák81e04022019-04-05 15:05:46 +0200586}
David Sedlákcd0c9512019-03-29 13:23:06 +0100587
David Sedlákda63c082019-06-04 13:52:23 +0200588LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200589yin_parse_import(struct lyxml_context *xml_ctx, struct yin_arg_record **import_args, const char *module_prefix, const char **data, struct lysp_import **imports)
David Sedlák736fd0d2019-02-15 16:06:31 +0100590{
David Sedlák736fd0d2019-02-15 16:06:31 +0100591 struct lysp_import *imp;
David Sedlák00250342019-06-21 14:19:39 +0200592 /* allocate new element in sized array for import */
David Sedlák3ffbc522019-07-02 17:49:28 +0200593 LY_ARRAY_NEW_RET(xml_ctx->ctx, *imports, imp, LY_EMEM);
594
595 struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_SELF, 0};
596 struct yin_subelement subelems[5] = {{YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
597 {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
598 {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
599 {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
600 {YANG_CUSTOM, &ext_info, 0}};
David Sedlák736fd0d2019-02-15 16:06:31 +0100601
David Sedláka7406952019-04-05 10:33:07 +0200602 /* parse import attributes */
David Sedlák3ffbc522019-07-02 17:49:28 +0200603 LY_CHECK_RET(yin_parse_attribute(xml_ctx, import_args, YIN_ARG_MODULE, &imp->name));
604 LY_CHECK_RET(yin_parse_content(xml_ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
605 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)xml_ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
David Sedlák00250342019-06-21 14:19:39 +0200606
David Sedlák3ffbc522019-07-02 17:49:28 +0200607 return yin_parse_content(xml_ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts);
David Sedlák736fd0d2019-02-15 16:06:31 +0100608}
609
David Sedlák11900c82019-06-18 16:29:12 +0200610LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200611yin_parse_status(struct lyxml_context *xml_ctx, struct yin_arg_record **status_args, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák11900c82019-06-18 16:29:12 +0200612{
David Sedlák3ffbc522019-07-02 17:49:28 +0200613 const char *value = NULL;
614 struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_STATUS, 0};
615 struct yin_subelement subelems[1] = {{YANG_CUSTOM, &ext_info, 0}};
616
David Sedlák11900c82019-06-18 16:29:12 +0200617 if (*flags & LYS_STATUS_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +0200618 LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPELEM, "status");
David Sedlák11900c82019-06-18 16:29:12 +0200619 return LY_EVALID;
620 }
621
David Sedlák8f7a1172019-06-20 14:42:18 +0200622 LY_CHECK_RET(yin_parse_attribute(xml_ctx, status_args, YIN_ARG_VALUE, &value));
David Sedlák11900c82019-06-18 16:29:12 +0200623 if (strcmp(value, "current") == 0) {
624 *flags |= LYS_STATUS_CURR;
625 } else if (strcmp(value, "deprecated") == 0) {
626 *flags |= LYS_STATUS_DEPRC;
627 } else if (strcmp(value, "obsolete") == 0) {
628 *flags |= LYS_STATUS_OBSLT;
629 } else {
David Sedlákb3077192019-06-19 10:55:37 +0200630 LOGVAL_PARSER(xml_ctx, LY_VCODE_INVAL_YIN, value, "status");
David Sedlák11900c82019-06-18 16:29:12 +0200631 lydict_remove(xml_ctx->ctx, value);
632 return LY_EVALID;
633 }
634 lydict_remove(xml_ctx->ctx, value);
635
David Sedlák3ffbc522019-07-02 17:49:28 +0200636 return yin_parse_content(xml_ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
David Sedlák11900c82019-06-18 16:29:12 +0200637}
638
David Sedlák11900c82019-06-18 16:29:12 +0200639LY_ERR
David Sedlák3ffbc522019-07-02 17:49:28 +0200640yin_parse_yin_element_element(struct lyxml_context *xml_ctx, struct yin_arg_record *attrs, const char **data,
641 uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák2721d3d2019-06-21 15:37:41 +0200642{
David Sedlák3ffbc522019-07-02 17:49:28 +0200643 const char *temp_val = NULL;
644 struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_YINELEM, 0};
645 struct yin_subelement subelems[1] = {{YANG_CUSTOM, &ext_info, 0}};
David Sedlák2721d3d2019-06-21 15:37:41 +0200646
David Sedlák3ffbc522019-07-02 17:49:28 +0200647 LY_CHECK_RET(yin_parse_attribute(xml_ctx, &attrs, YIN_ARG_VALUE, &temp_val));
David Sedlák2721d3d2019-06-21 15:37:41 +0200648 if (strcmp(temp_val, "true") == 0) {
649 *flags |= LYS_YINELEM_TRUE;
650 } else if (strcmp(temp_val, "false") == 0) {
651 *flags |= LYS_YINELEM_FALSE;
652 } else {
653 LOGVAL_PARSER(xml_ctx, LY_VCODE_INVAL_YIN, temp_val, "yin-element");
654 lydict_remove(xml_ctx->ctx, temp_val);
655 return LY_EVALID;
656 }
657 lydict_remove(xml_ctx->ctx, temp_val);
658
David Sedlák3ffbc522019-07-02 17:49:28 +0200659 return yin_parse_content(xml_ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
David Sedlák2721d3d2019-06-21 15:37:41 +0200660}
661
662LY_ERR
David Sedlák3ffbc522019-07-02 17:49:28 +0200663yin_parse_extension_instance(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data, const char *ext_name,
664 int ext_name_len, struct yin_ext_meta *metadata, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +0200665{
666 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +0200667 char *out;
668 const char *name, *prefix;
669 size_t out_len, prefix_len, name_len;
670 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +0200671 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +0200672 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
673 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +0200674
675 LY_ARRAY_NEW_RET(xml_ctx->ctx, *exts, e, LY_EMEM);
676
677 e->yin = 0;
678 /* store name and insubstmt info */
679 e->name = lydict_insert(xml_ctx->ctx, ext_name, ext_name_len);
David Sedlák3ffbc522019-07-02 17:49:28 +0200680 e->insubstmt = metadata->subelem;
681 e->insubstmt_index = metadata->subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +0200682 e->yin |= LYS_YIN;
683
David Sedlákb1a78352019-06-28 16:16:29 +0200684 /* store attributes as subelements */
685 LY_ARRAY_FOR_ITER(*attrs, struct yin_arg_record, iter) {
686 if (!iter->prefix) {
687 new_subelem = calloc(1, sizeof(*new_subelem));
688 if (!e->child) {
689 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +0200690 } else {
David Sedlákb1a78352019-06-28 16:16:29 +0200691 last_subelem->next = new_subelem;
692 }
693 last_subelem = new_subelem;
694
695 last_subelem->flags |= LYS_YIN_ATTR;
696 last_subelem->stmt = lydict_insert(xml_ctx->ctx, iter->name, iter->name_len);
697 LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(xml_ctx->ctx), LY_EMEM);
698 if (iter->dynamic_content) {
699 last_subelem->arg = lydict_insert_zc(xml_ctx->ctx, iter->content);
700 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(xml_ctx->ctx), LY_EMEM);
701 } else {
702 last_subelem->arg = lydict_insert(xml_ctx->ctx, iter->content, iter->content_len);
703 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +0200704 }
705 }
706 }
David Sedlák1e2cdd02019-06-27 14:17:43 +0200707
David Sedlákf250ecf2019-07-01 11:02:05 +0200708 /* parse subelements */
David Sedlákb1a78352019-06-28 16:16:29 +0200709 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
710 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
711 if (ret == LY_EINVAL) {
712 while (xml_ctx->status == LYXML_ELEMENT) {
713 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
714 if (!name) {
715 /* end of extension instance reached */
716 break;
717 }
David Sedlákf250ecf2019-07-01 11:02:05 +0200718 LY_CHECK_RET(yin_parse_element_generic(xml_ctx, name, name_len, prefix, prefix_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +0200719 if (!e->child) {
720 e->child = new_subelem;
721 } else {
722 last_subelem->next = new_subelem;
723 }
724 last_subelem = new_subelem;
725 }
726 }
727 } else {
728 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
729 LY_CHECK_RET(name, LY_EINVAL);
730 }
731
732 return LY_SUCCESS;
733}
734
735LY_ERR
David Sedlákf250ecf2019-07-01 11:02:05 +0200736yin_parse_element_generic(struct lyxml_context *xml_ctx, const char *name, size_t name_len, const char *prefix,
737 size_t prefix_len, const char **data, struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +0200738{
739 LY_ERR ret = LY_SUCCESS;
740 const char *temp_prefix, *temp_name;
741 char *out = NULL;
David Sedlákf250ecf2019-07-01 11:02:05 +0200742 size_t out_len, temp_name_len, temp_prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +0200743 int dynamic;
744 struct yin_arg_record *subelem_args = NULL;
745 struct lysp_stmt *last = NULL, *new = NULL;
746
747 /* allocate new structure for element */
748 *element = calloc(1, sizeof(**element));
749 (*element)->stmt = lydict_insert(xml_ctx->ctx, name, name_len);
750 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(xml_ctx->ctx), LY_EMEM);
751
752 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +0200753 /* load attributes */
David Sedlákb1a78352019-06-28 16:16:29 +0200754 while(xml_ctx->status == LYXML_ATTRIBUTE) {
755 /* add new element to linked-list */
756 new = calloc(1, sizeof(*last));
757 LY_CHECK_ERR_GOTO(ret, LOGMEM(xml_ctx->ctx), err);
758 if (!(*element)->child) {
759 /* save first */
760 (*element)->child = new;
761 } else {
762 last->next = new;
763 }
764 last = new;
765
766 last->flags |= LYS_YIN_ATTR;
767 ret = lyxml_get_attribute(xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
768 LY_CHECK_GOTO(ret, err);
769 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
770 LY_CHECK_GOTO(ret, err);
771 last->stmt = lydict_insert(xml_ctx->ctx, temp_name, temp_name_len);
772 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(xml_ctx->ctx); ret = LY_EMEM, err);
773 /* attributes with prefix are ignored */
774 if (!temp_prefix) {
775 if (dynamic) {
776 last->arg = lydict_insert_zc(xml_ctx->ctx, out);
777 if (!last->arg) {
778 free(out);
779 LOGMEM(xml_ctx->ctx);
780 ret = LY_EMEM;
781 goto err;
782 }
783 } else {
784 last->arg = lydict_insert(xml_ctx->ctx, out, out_len);
785 LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(xml_ctx->ctx); ret = LY_EMEM, err);
786 }
787 }
788 }
789
790 /* parse content of element */
791 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
792 if (ret == LY_EINVAL) {
793 while (xml_ctx->status == LYXML_ELEMENT) {
794 /* parse subelements */
David Sedlákf250ecf2019-07-01 11:02:05 +0200795 ret = lyxml_get_element(xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
David Sedlákb1a78352019-06-28 16:16:29 +0200796 LY_CHECK_GOTO(ret, err);
797 if (!name) {
798 /* end of element reached */
799 break;
800 }
David Sedlákf250ecf2019-07-01 11:02:05 +0200801 ret = yin_parse_element_generic(xml_ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, data, &last->next);
David Sedlákb1a78352019-06-28 16:16:29 +0200802 LY_CHECK_GOTO(ret, err);
803 last = last->next;
804 }
805 } else {
806 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +0200807 if (out_len != 0) {
808 if (dynamic) {
809 (*element)->arg = lydict_insert_zc(xml_ctx->ctx, out);
810 if (!(*element)->arg) {
811 free(out);
812 LOGMEM(xml_ctx->ctx);
813 ret = LY_EMEM;
814 goto err;
815 }
816 } else {
817 (*element)->arg = lydict_insert(xml_ctx->ctx, out, out_len);
818 LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(xml_ctx->ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +0200819 }
David Sedlákb1a78352019-06-28 16:16:29 +0200820 }
821 /* read closing tag */
822 ret = lyxml_get_element(xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
823 LY_CHECK_GOTO(ret, err);
824 }
825
826 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
827 return LY_SUCCESS;
828
829err:
830 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +0200831 return ret;
832}
833
David Sedlák3ffbc522019-07-02 17:49:28 +0200834/**
835 * @brief Parse argument element.
836 *
837 * @param[in,out] xml_ctx Xml context.
838 * @param[in] attrs Attributes of this element.
839 * @param[in,out] data Data to read from, always moved to currently handled character.
840 * @param[in,out] arg_meta Meta information about destionation af prased data.
841 * @param[in,out] exts Extension instance to add to.
842 *
843 * @return LY_ERR values.
844 */
David Sedlák1e2cdd02019-06-27 14:17:43 +0200845LY_ERR
David Sedlák9494eb22019-06-21 16:06:53 +0200846yin_parse_argument_element(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data,
David Sedlák3ffbc522019-07-02 17:49:28 +0200847 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
David Sedlák9494eb22019-06-21 16:06:53 +0200848{
David Sedlák3ffbc522019-07-02 17:49:28 +0200849 struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_ARGUMENT, 0};
850 struct yin_subelement subelems[2] = {{YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
851 {YANG_CUSTOM, &ext_info, 0}};
David Sedlák9494eb22019-06-21 16:06:53 +0200852
David Sedlák3ffbc522019-07-02 17:49:28 +0200853 LY_CHECK_RET(yin_parse_attribute(xml_ctx, attrs, YIN_ARG_NAME, arg_meta->argument));
David Sedlák9494eb22019-06-21 16:06:53 +0200854
David Sedlák3ffbc522019-07-02 17:49:28 +0200855 return yin_parse_content(xml_ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
David Sedlák9494eb22019-06-21 16:06:53 +0200856}
857
858LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200859yin_parse_extension(struct lyxml_context *xml_ctx, struct yin_arg_record **extension_args, const char **data, struct lysp_ext **extensions)
David Sedlák11900c82019-06-18 16:29:12 +0200860{
David Sedlák11900c82019-06-18 16:29:12 +0200861 struct lysp_ext *ex;
David Sedlák3ffbc522019-07-02 17:49:28 +0200862 LY_ARRAY_NEW_RET(xml_ctx->ctx, *extensions, ex, LY_EMEM);
863 LY_CHECK_RET(yin_parse_attribute(xml_ctx, extension_args, YIN_ARG_NAME, &ex->name));
864 struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_SELF, 0};
865 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
866 struct yin_subelement subelems[5] = {{YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
867 {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
868 {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
869 {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
870 {YANG_CUSTOM, &ext_info, 0}};
David Sedlák11900c82019-06-18 16:29:12 +0200871
David Sedlák3ffbc522019-07-02 17:49:28 +0200872 return yin_parse_content(xml_ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
David Sedlák11900c82019-06-18 16:29:12 +0200873}
874
David Sedlák00250342019-06-21 14:19:39 +0200875/**
876 * @brief Parse module substatements.
877 *
878 * @param[in] xml_ctx Xml context.
879 * @param[in,out] data Data to read from.
880 * @param[out] mod Parsed module structure.
881 *
882 * @return LY_ERR values.
883 */
884LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200885yin_parse_mod(struct lyxml_context *xml_ctx, struct yin_arg_record **mod_args, const char **data, struct lysp_module **mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200886{
David Sedlákf3b24f62018-11-02 10:40:47 +0100887 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100888 enum yang_keyword kw = YANG_NONE;
David Sedláke4889912018-11-02 09:52:40 +0100889 const char *prefix, *name;
David Sedlák3b4db242018-10-19 16:11:01 +0200890 size_t prefix_len, name_len;
David Sedlák4b4713f2019-02-15 13:47:45 +0100891 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
David Sedlák3b4db242018-10-19 16:11:01 +0200892
David Sedlákf3b24f62018-11-02 10:40:47 +0100893 char *buf = NULL, *out = NULL;
894 size_t buf_len = 0, out_len = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200895 int dynamic = 0;
David Sedlák8f7a1172019-06-20 14:42:18 +0200896 struct yin_arg_record *substmt_args = NULL;
David Sedlákf3b24f62018-11-02 10:40:47 +0100897
David Sedlák8f7a1172019-06-20 14:42:18 +0200898 yin_parse_attribute(xml_ctx, mod_args, YIN_ARG_NAME, &(*mod)->mod->name);
David Sedlákb3077192019-06-19 10:55:37 +0200899 LY_CHECK_ERR_RET(!(*mod)->mod->name, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Missing argument name of a module"), LY_EVALID);
David Sedlákc136b972019-03-08 13:39:06 +0100900 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlákb3077192019-06-19 10:55:37 +0200901 LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected new xml element after module element."), LY_EINVAL);
David Sedlák4a4c0722018-11-26 17:03:10 +0100902
David Sedlák736fd0d2019-02-15 16:06:31 +0100903 /* loop over all elements and parse them */
David Sedlákc136b972019-03-08 13:39:06 +0100904 while (xml_ctx->status != LYXML_END) {
David Sedlák4b4713f2019-02-15 13:47:45 +0100905#define CHECK_ORDER(SECTION) \
906 if (mod_stmt > SECTION) {return LY_EVALID;}mod_stmt = SECTION
907
908 switch (kw) {
909 /* module header */
910 case YANG_NAMESPACE:
911 case YANG_PREFIX:
912 CHECK_ORDER(Y_MOD_MODULE_HEADER);
913 break;
914 case YANG_YANG_VERSION:
915 CHECK_ORDER(Y_MOD_MODULE_HEADER);
916 break;
917 /* linkage */
918 case YANG_INCLUDE:
919 case YANG_IMPORT:
920 CHECK_ORDER(Y_MOD_LINKAGE);
921 break;
922 /* meta */
923 case YANG_ORGANIZATION:
924 case YANG_CONTACT:
925 case YANG_DESCRIPTION:
926 case YANG_REFERENCE:
927 CHECK_ORDER(Y_MOD_META);
928 break;
929
930 /* revision */
931 case YANG_REVISION:
932 CHECK_ORDER(Y_MOD_REVISION);
933 break;
934 /* body */
935 case YANG_ANYDATA:
936 case YANG_ANYXML:
937 case YANG_AUGMENT:
938 case YANG_CHOICE:
939 case YANG_CONTAINER:
940 case YANG_DEVIATION:
941 case YANG_EXTENSION:
942 case YANG_FEATURE:
943 case YANG_GROUPING:
944 case YANG_IDENTITY:
945 case YANG_LEAF:
946 case YANG_LEAF_LIST:
947 case YANG_LIST:
948 case YANG_NOTIFICATION:
949 case YANG_RPC:
950 case YANG_TYPEDEF:
951 case YANG_USES:
952 case YANG_CUSTOM:
953 mod_stmt = Y_MOD_BODY;
954 break;
955 default:
956 /* error will be handled in the next switch */
957 break;
958 }
959#undef CHECK_ORDER
960
David Sedlák68826732019-06-05 10:50:58 +0200961 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákc136b972019-03-08 13:39:06 +0100962 if (name) {
David Sedlák8f7a1172019-06-20 14:42:18 +0200963 LY_CHECK_RET(yin_load_attributes(xml_ctx, data, &substmt_args));
964 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlákc136b972019-03-08 13:39:06 +0100965 switch (kw) {
David Sedlák736fd0d2019-02-15 16:06:31 +0100966
David Sedlákc136b972019-03-08 13:39:06 +0100967 /* module header */
968 case YANG_NAMESPACE:
David Sedlák00250342019-06-21 14:19:39 +0200969 ret = yin_parse_attribute(xml_ctx, &substmt_args, YIN_ARG_URI, &(*mod)->mod->ns);
970 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +0100971 break;
972 case YANG_PREFIX:
David Sedlák00250342019-06-21 14:19:39 +0200973 ret = yin_parse_attribute(xml_ctx, &substmt_args, YIN_ARG_VALUE, &(*mod)->mod->prefix);
974 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +0100975 break;
David Sedlák4a4c0722018-11-26 17:03:10 +0100976
David Sedlákc136b972019-03-08 13:39:06 +0100977 /* linkage */
978 case YANG_IMPORT:
David Sedlák00250342019-06-21 14:19:39 +0200979 ret = yin_parse_import(xml_ctx, &substmt_args, (*mod)->mod->prefix, data, &(*mod)->imports);
980 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +0100981 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100982
David Sedlákc136b972019-03-08 13:39:06 +0100983 /* meta */
984 case YANG_ORGANIZATION:
David Sedlák3ffbc522019-07-02 17:49:28 +0200985 ret = yin_parse_meta_element(xml_ctx, data, YANG_ORGANIZATION, &(*mod)->mod->org, NULL);
David Sedlák00250342019-06-21 14:19:39 +0200986 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +0100987 break;
988 case YANG_CONTACT:
David Sedlák3ffbc522019-07-02 17:49:28 +0200989 ret = yin_parse_meta_element(xml_ctx, data, YANG_CONTACT, &(*mod)->mod->contact, NULL);
David Sedlák00250342019-06-21 14:19:39 +0200990 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +0100991 break;
992 case YANG_DESCRIPTION:
David Sedlák3ffbc522019-07-02 17:49:28 +0200993 ret = yin_parse_meta_element(xml_ctx, data, YANG_DESCRIPTION, &(*mod)->mod->dsc, NULL);
David Sedlák00250342019-06-21 14:19:39 +0200994 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +0100995 break;
996 case YANG_REFERENCE:
David Sedlák3ffbc522019-07-02 17:49:28 +0200997 ret = yin_parse_meta_element(xml_ctx, data, YANG_REFERENCE, &(*mod)->mod->ref, NULL);
David Sedlák00250342019-06-21 14:19:39 +0200998 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +0100999 break;
David Sedlák11900c82019-06-18 16:29:12 +02001000 /* revision */
1001
1002 /*body */
1003 case YANG_EXTENSION:
David Sedlák00250342019-06-21 14:19:39 +02001004 ret = yin_parse_extension(xml_ctx, &substmt_args, data, &(*mod)->extensions);
1005 LY_CHECK_GOTO(ret, error);
David Sedlák11900c82019-06-18 16:29:12 +02001006 break;
David Sedlák736fd0d2019-02-15 16:06:31 +01001007
David Sedlákc136b972019-03-08 13:39:06 +01001008 default:
David Sedlák00250342019-06-21 14:19:39 +02001009 ret = LY_EVALID;
1010 goto error;
David Sedlákc136b972019-03-08 13:39:06 +01001011 }
David Sedlák00250342019-06-21 14:19:39 +02001012 FREE_ARRAY(xml_ctx, substmt_args, free_arg_rec);
David Sedlák8f7a1172019-06-20 14:42:18 +02001013 substmt_args = NULL;
David Sedlák4a4c0722018-11-26 17:03:10 +01001014 }
1015 }
1016
David Sedlák68826732019-06-05 10:50:58 +02001017 return LY_SUCCESS;
David Sedlák00250342019-06-21 14:19:39 +02001018
1019error:
1020 FREE_ARRAY(xml_ctx, substmt_args, free_arg_rec);
1021 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02001022}
1023
1024LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +01001025yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02001026{
David Sedláke4889912018-11-02 09:52:40 +01001027 LY_ERR ret = LY_SUCCESS;
1028 enum yang_keyword kw = YANG_NONE;
David Sedlákecf5eb82019-06-03 14:12:44 +02001029 struct lys_parser_ctx parser_ctx;
David Sedlákaadab9c2019-04-05 15:01:27 +02001030 struct lyxml_context *xml_ctx = (struct lyxml_context *)&parser_ctx;
David Sedlák3017da42019-02-15 09:48:04 +01001031 struct lysp_module *mod_p = NULL;
1032 const char *prefix, *name;
1033 size_t prefix_len, name_len;
David Sedlák8f7a1172019-06-20 14:42:18 +02001034 struct yin_arg_record *args = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02001035
David Sedlák3017da42019-02-15 09:48:04 +01001036 /* initialize xml context */
David Sedlákaadab9c2019-04-05 15:01:27 +02001037 memset(&parser_ctx, 0, sizeof parser_ctx);
1038 xml_ctx->ctx = ctx;
1039 xml_ctx->line = 1;
David Sedláke4889912018-11-02 09:52:40 +01001040
David Sedlák3017da42019-02-15 09:48:04 +01001041 /* check submodule */
David Sedlákaadab9c2019-04-05 15:01:27 +02001042 ret = lyxml_get_element(xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02001043 LY_CHECK_GOTO(ret, cleanup);
1044 ret = yin_load_attributes(xml_ctx, &data, &args);
1045 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8f7a1172019-06-20 14:42:18 +02001046 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedláke4889912018-11-02 09:52:40 +01001047 if (kw == YANG_SUBMODULE) {
David Sedlák3017da42019-02-15 09:48:04 +01001048 LOGERR(ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
1049 ret = LY_EINVAL;
1050 goto cleanup;
1051 } else if (kw != YANG_MODULE) {
David Sedlákb3077192019-06-19 10:55:37 +02001052 LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
David Sedlák79e50cb2019-06-05 16:33:09 +02001053 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01001054 ret = LY_EVALID;
1055 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01001056 }
1057
David Sedlák3017da42019-02-15 09:48:04 +01001058 /* allocate module */
1059 mod_p = calloc(1, sizeof *mod_p);
1060 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
1061 mod_p->mod = mod;
1062 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01001063
David Sedlák00250342019-06-21 14:19:39 +02001064 /* parse module substatements */
David Sedlák8f7a1172019-06-20 14:42:18 +02001065 ret = yin_parse_mod(xml_ctx, &args, &data, &mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01001066 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01001067
David Sedlák3017da42019-02-15 09:48:04 +01001068 mod_p->parsing = 0;
1069 mod->parsed = mod_p;
1070
1071cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02001072 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01001073 lysp_module_free(mod_p);
1074 }
David Sedlák00250342019-06-21 14:19:39 +02001075 FREE_ARRAY(xml_ctx, args, free_arg_rec);
David Sedlákaadab9c2019-04-05 15:01:27 +02001076 lyxml_context_clear(xml_ctx);
David Sedlák2e411422018-12-17 02:35:39 +01001077 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02001078}