blob: 88022671779802edb60e56478293fbdcf5608549 [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á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ákd6e56892019-07-01 15:40:24 +020020#include <stdbool.h>
David Sedlákf824ad52018-10-14 23:58:15 +020021
David Sedlákf824ad52018-10-14 23:58:15 +020022#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020023#include "dict.h"
David Sedlák3b4db242018-10-19 16:11:01 +020024#include "xml.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020025#include "tree.h"
26#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020027#include "tree_schema_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020028#include "parser_yin.h"
David Sedlák00250342019-06-21 14:19:39 +020029
David Sedlák2b214ac2019-06-06 16:11:03 +020030/**
31 * @brief check if given string is URI of yin namespace.
32 * @param ns Namespace URI to check.
33 *
34 * @return true if ns equals YIN_NS_URI false otherwise.
35 */
36#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
37
David Sedlák9bc65872019-06-24 20:21:08 +020038/**
39 * @brief loop over all subelements, automatically skip useles data and
40 * unify inconsistencies in xml parser status when loading full vs self closing tags.
41 * Use YIN_READ_SUBELEMS_END at the end.
42 *
43 * @param[in,out] CTX Xml parser context.
44 * @param[in,out] DATA Data to read from, always moved to currently handeled character.
45 * @param[in,out] RET Name of variable to store return values.
46 * @param[in,out] CLEANUP_LABEL Goto label that will be used in case of error.
47 * @param[in,out] KW Name of variable to store type of current subelement.
48 * @param[in] TMP Name of variable to store temporary values (type yin_arg_record).
49 * @param[in] SUBELEM_ARGS Name of variable to store array of subelements.
50 */
51#define YIN_READ_SUBELEMS_START(CTX, DATA, RET, CLEANUP_LABEL, KW, TMP, SUBELEM_ARGS)\
52if (xml_ctx->status == LYXML_ELEM_CONTENT) {\
53 ret = lyxml_get_string(CTX, DATA, &TMP.content, &TMP.content_len, &TMP.content, &TMP.content_len, &TMP.dynamic_content);\
54 /* unknown element text content is ignored */\
55 if (ret == LY_EINVAL) {\
56 while (CTX->status == LYXML_ELEMENT) {\
57 RET = lyxml_get_element(CTX, DATA, &TMP.prefix, &TMP.prefix_len, &TMP.name, &TMP.name_len);\
58 LY_CHECK_GOTO(RET, CLEANUP_LABEL);\
59 RET = yin_load_attributes(CTX, DATA, &SUBELEM_ARGS);\
60 LY_CHECK_GOTO(RET, CLEANUP_LABEL);\
61 KW = yin_match_keyword(CTX, TMP.name, TMP.name_len, TMP.prefix, TMP.prefix_len);\
62 if (!TMP.name) {\
David Sedlákb1a78352019-06-28 16:16:29 +020063 /* end of element reached */\
David Sedlák9bc65872019-06-24 20:21:08 +020064 break;\
65 }
66/**
67 * Closing part of macro YIN_READ_SUBELEM_START
68 *
69 * @param[in] CTX Xml parser context.
70 * @param[in,out] DATA Data to read from, always moved to currently handeled character.
71 * @param[in,out] TMP Name of variable to store temporary values (type yin_arg_record).
72 */
73#define YIN_READ_SUBELEMS_END(CTX, DATA, TMP)\
74 }\
75 } else {\
76 /* load closing element */\
David Sedlák1e2cdd02019-06-27 14:17:43 +020077 LY_CHECK_RET(lyxml_get_element(CTX, DATA, &TMP.prefix, &TMP.prefix_len, &TMP.name, &TMP.name_len));\
78 LY_CHECK_RET(TMP.name, LY_EINVAL);\
David Sedlák9bc65872019-06-24 20:21:08 +020079 }\
80}
81
David Sedlákf6251182019-06-06 10:22:13 +020082const char *const yin_attr_list[] = {
83 [YIN_ARG_NAME] = "name",
84 [YIN_ARG_TARGET_NODE] = "target-node",
85 [YIN_ARG_MODULE] = "module",
86 [YIN_ARG_VALUE] = "value",
87 [YIN_ARG_TEXT] = "text",
88 [YIN_ARG_CONDITION] = "condition",
89 [YIN_ARG_URI] = "uri",
90 [YIN_ARG_DATE] = "date",
91 [YIN_ARG_TAG] = "tag",
92 [YIN_ARG_XMLNS] = "xmlns",
93};
94
David Sedlák1bccdfa2019-06-17 15:55:27 +020095enum yang_keyword
David Sedlák8f7a1172019-06-20 14:42:18 +020096yin_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 +020097{
David Sedlák8f7a1172019-06-20 14:42:18 +020098 const char *start = NULL;
99 enum yang_keyword kw = YANG_NONE;
100 const struct lyxml_ns *ns = NULL;
101
102 if (!name || name_len == 0) {
David Sedlák1bccdfa2019-06-17 15:55:27 +0200103 return YANG_NONE;
104 }
105
David Sedlák8f7a1172019-06-20 14:42:18 +0200106 ns = lyxml_ns_get(xml_ctx, prefix, prefix_len);
107 if (ns) {
108 if (!IS_YIN_NS(ns->uri)) {
109 return YANG_CUSTOM;
110 }
111 } else {
112 /* elements without namespace are automatically unknown */
113 return YANG_NONE;
114 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200115
David Sedlák8f7a1172019-06-20 14:42:18 +0200116
117 start = name;
118 kw = lysp_match_kw(NULL, &name);
119
120 if (name - start == (long int)name_len) {
David Sedlák1bccdfa2019-06-17 15:55:27 +0200121 return kw;
122 } else {
123 return YANG_NONE;
124 }
125}
126
David Sedlák872c7b42018-10-26 13:15:20 +0200127enum YIN_ARGUMENT
David Sedlák060b00e2019-06-19 11:12:06 +0200128yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200129{
David Sedláka7406952019-04-05 10:33:07 +0200130 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200131 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200132 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200133
David Sedlák94de2aa2019-02-15 12:42:11 +0100134#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
135#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100136#define IF_ARG_PREFIX_END }
137
David Sedlák1c8b2702019-02-22 11:03:02 +0100138 switch (*name) {
David Sedlák18730132019-03-15 15:51:34 +0100139 case 'x':
140 already_read += 1;
141 IF_ARG("mlns", 4, YIN_ARG_XMLNS);
142 break;
David Sedlák94de2aa2019-02-15 12:42:11 +0100143 case 'c':
144 already_read += 1;
145 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200146 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200147
David Sedlák94de2aa2019-02-15 12:42:11 +0100148 case 'd':
149 already_read += 1;
150 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200151 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200152
David Sedlák94de2aa2019-02-15 12:42:11 +0100153 case 'm':
154 already_read += 1;
155 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200156 break;
157
David Sedlák94de2aa2019-02-15 12:42:11 +0100158 case 'n':
159 already_read += 1;
160 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200161 break;
162
David Sedlák94de2aa2019-02-15 12:42:11 +0100163 case 't':
164 already_read += 1;
165 IF_ARG_PREFIX("a", 1)
166 IF_ARG("g", 1, YIN_ARG_TAG)
167 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
168 IF_ARG_PREFIX_END
169 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200170 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200171
David Sedlák94de2aa2019-02-15 12:42:11 +0100172 case 'u':
173 already_read += 1;
174 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200175 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200176
David Sedlák94de2aa2019-02-15 12:42:11 +0100177 case 'v':
178 already_read += 1;
179 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200180 break;
181 }
182
David Sedlákc10e7902018-12-17 02:17:59 +0100183 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200184 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200185 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200186 }
187
David Sedlák18730132019-03-15 15:51:34 +0100188#undef IF_ARG
189#undef IF_ARG_PREFIX
190#undef IF_ARG_PREFIX_END
191
David Sedlák872c7b42018-10-26 13:15:20 +0200192 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200193}
194
David Sedlák00250342019-06-21 14:19:39 +0200195static void free_arg_rec(struct lyxml_context *xml_ctx, struct yin_arg_record *record) {
196 (void)xml_ctx; /* unused */
197 if (record->dynamic_content) {
198 free(record->content);
199 }
200}
201
David Sedlák8f7a1172019-06-20 14:42:18 +0200202LY_ERR
203yin_load_attributes(struct lyxml_context *xml_ctx, const char **data, struct yin_arg_record **args)
David Sedláka7406952019-04-05 10:33:07 +0200204{
205 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200206 struct yin_arg_record *argument_record = NULL;
David Sedláka7406952019-04-05 10:33:07 +0200207
David Sedlák7ff55a92019-06-17 11:11:41 +0200208 /* load all attributes first */
David Sedlák57715b12019-06-17 13:05:22 +0200209 while (xml_ctx->status == LYXML_ATTRIBUTE) {
David Sedlák8f7a1172019-06-20 14:42:18 +0200210 LY_ARRAY_NEW_GOTO(xml_ctx->ctx, *args, argument_record, ret, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200211 ret = lyxml_get_attribute(xml_ctx, data, &argument_record->prefix, &argument_record->prefix_len,
212 &argument_record->name, &argument_record->name_len);
David Sedlák00250342019-06-21 14:19:39 +0200213 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200214
David Sedlák7ff55a92019-06-17 11:11:41 +0200215 if (xml_ctx->status == LYXML_ATTR_CONTENT) {
David Sedlák57715b12019-06-17 13:05:22 +0200216 argument_record->content = NULL;
217 argument_record->content_len = 0;
218 argument_record->dynamic_content = 0;
219 ret = lyxml_get_string(xml_ctx, data, &argument_record->content, &argument_record->content_len,
220 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák00250342019-06-21 14:19:39 +0200221 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200222 }
223 }
224
David Sedlák8f7a1172019-06-20 14:42:18 +0200225cleanup:
226 if (ret != LY_SUCCESS) {
David Sedlák00250342019-06-21 14:19:39 +0200227 FREE_ARRAY(xml_ctx, *args, free_arg_rec);
228 *args = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200229 }
230 return ret;
231}
232
233LY_ERR
234yin_parse_attribute(struct lyxml_context *xml_ctx, struct yin_arg_record **args, enum YIN_ARGUMENT arg_type, const char **arg_val)
235{
236 LY_ERR ret = LY_SUCCESS;
237 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
238 struct yin_arg_record *iter = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200239
David Sedlák1bccdfa2019-06-17 15:55:27 +0200240 /* validation of attributes */
David Sedlák8f7a1172019-06-20 14:42:18 +0200241 LY_ARRAY_FOR(*args, struct yin_arg_record, iter) {
David Sedlák00250342019-06-21 14:19:39 +0200242 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
243 if (!iter->prefix) {
David Sedlák060b00e2019-06-19 11:12:06 +0200244 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200245 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200246 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200247 } else if (arg == arg_type) {
David Sedlák57715b12019-06-17 13:05:22 +0200248 if (iter->dynamic_content) {
249 *arg_val = lydict_insert_zc(xml_ctx->ctx, iter->content);
David Sedlák00250342019-06-21 14:19:39 +0200250 LY_CHECK_ERR_GOTO(!(*arg_val), LOGMEM(xml_ctx->ctx); ret = LY_EMEM, cleanup);
251 /* string is no longer supposed to be freed when the sized array is freed */
252 iter->dynamic_content = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200253 } else {
254 *arg_val = lydict_insert(xml_ctx->ctx, iter->content, iter->content_len);
255 LY_CHECK_ERR_GOTO(!(*arg_val), LOGMEM(xml_ctx->ctx); ret = LY_EMEM, cleanup);
256 }
David Sedlák2b214ac2019-06-06 16:11:03 +0200257 } else {
David Sedlák7ff55a92019-06-17 11:11:41 +0200258 LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected attribute \"%.*s\".", iter->name_len, iter->name);
259 ret = LY_EVALID;
260 goto cleanup;
David Sedláka7406952019-04-05 10:33:07 +0200261 }
262 }
263 }
264
David Sedlák7ff55a92019-06-17 11:11:41 +0200265cleanup:
David Sedlák7ff55a92019-06-17 11:11:41 +0200266 return ret;
David Sedláka7406952019-04-05 10:33:07 +0200267}
268
David Sedlákd6e56892019-07-01 15:40:24 +0200269struct yin_attribute {
270 enum YIN_ARGUMENT type;
271 bool mandatory;
272 const char *dest;
273};
274
275struct yin_subelement {
276 enum yang_keyword type;
277 bool mandatory;
278 void *dest;
279};
280
281struct sized_string {
282 const char *value;
283 size_t len;
284};
285
286/**
287 * @brief get record with given type.
288 *
289 * @param[in] type Type of wanted record.
290 * @param[in] array_size Size of array.
291 * @param[in] array Searched array.
292 *
293 * @return Pointer to desired record on success, NULL if element is not in the array.
294 */
295struct yin_subelement *
296get_record(enum yang_keyword type, size_t array_size, struct yin_subelement *array)
297{
298 for (size_t i = 0; i < array_size; ++i) {
299 if (array[i].type == type) {
300 return &array[i];
301 }
302 }
303
304 return NULL;
305}
306
307/**
308 * @brief Generic function for subelement parsing
309 *
310 * @param[in,out] xml_ctx Xml context.
311 * @param[in] attrs Array of attributes.
312 * @param[in] subelem_info array of valid subelement types and meta information.
313 * @param[in] subelem_info_size Size of subelem_info array.
314 * @param[in] current_element Type of current element.
315 * @param[in,out] data Data to read from, always moved to currently handled character.
316 * @param[in] subelem Type of this subelement.
317 * @param[in] subelem_index Index of this subelement.
318 * @param[in] exts Extension instances to add to.
319 *
320 * @return LY_ERR values.
321 */
322LY_ERR
323yin_parse_element(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
324 enum yang_keyword current_element, const char **data, LYEXT_SUBSTMT subelem,
325 uint32_t subelem_index, struct lysp_ext_instance *exts)
326{
327 LY_ERR ret = LY_SUCCESS;
328 struct sized_string prefix, name;
329 char *out;
330 size_t out_len;
331 int dynamic;
332 struct yin_arg_record *subelem_attrs;
333 enum yang_keyword kw = YANG_NONE;
334 struct yin_subelement *subeleme_info_rec;
335
336 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
337 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
338 /* current element has subelements as content */
339 if (ret == LY_EINVAL) {
340 while (xml_ctx->status == LYXML_ELEMENT) {
341 ret = lyxml_get_element(xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len);
342 LY_CHECK_GOTO(ret, cleanup);
343 if (!name.value) {
344 /* end of current element reached */
345 break;
346 }
347 ret = yin_load_attributes(xml_ctx, data, &subelem_attrs);
348 LY_CHECK_GOTO(ret, cleanup);
349 kw = yin_match_keyword(xml_ctx, name.value, name.len, prefix.value, prefix.len);
350
351 /* check if this element can be child of current element */
352 subeleme_info_rec = get_record(kw, subelem_info_size, subelem_info);
353 if (!subeleme_info_rec) {
354 LOGVAL_PARSER(xml_ctx, LY_VCODE_UNEXP_SUBELEM, name.len, name.value, ly_stmt2str(current_element));
355 ret = LY_EVALID;
356 goto cleanup;
357 }
358
359 /* TODO macro to check order */
360
361 switch (kw) {
362 case YANG_CUSTOM:
363 yin_parse_extension_instance(xml_ctx, subelem_attrs, data, name2fullname(name.value, prefix.len),
364 namelen2fulllen(name.len, prefix.len), subelem, subelem_index, &exts);
365 break;
366 case YANG_ACTION:
367 break;
368 case YANG_ANYDATA:
369 break;
370 case YANG_ANYXML:
371 break;
372 case YANG_ARGUMENT:
373 break;
374 case YANG_AUGMENT:
375 break;
376 case YANG_BASE:
377 break;
378 case YANG_BELONGS_TO:
379 break;
380 case YANG_BIT:
381 break;
382 case YANG_CASE:
383 break;
384 case YANG_CHOICE:
385 break;
386 case YANG_CONFIG:
387 break;
388 case YANG_CONTACT:
389 break;
390 case YANG_CONTAINER:
391 break;
392 case YANG_DEFAULT:
393 break;
394 case YANG_DESCRIPTION:
395 break;
396 case YANG_DEVIATE:
397 break;
398 case YANG_DEVIATION:
399 break;
400 case YANG_ENUM:
401 break;
402 case YANG_ERROR_APP_TAG:
403 break;
404 case YANG_ERROR_MESSAGE:
405 break;
406 case YANG_EXTENSION:
407 break;
408 case YANG_FEATURE:
409 break;
410 case YANG_FRACTION_DIGITS:
411 break;
412 case YANG_GROUPING:
413 break;
414 case YANG_IDENTITY:
415 break;
416 case YANG_IF_FEATURE:
417 break;
418 case YANG_IMPORT:
419 break;
420 case YANG_INCLUDE:
421 break;
422 case YANG_INPUT:
423 break;
424 case YANG_KEY:
425 break;
426 case YANG_LEAF:
427 break;
428 case YANG_LEAF_LIST:
429 break;
430 case YANG_LENGTH:
431 break;
432 case YANG_LIST:
433 break;
434 case YANG_MANDATORY:
435 break;
436 case YANG_MAX_ELEMENTS:
437 break;
438 case YANG_MIN_ELEMENTS:
439 break;
440 case YANG_MODIFIER:
441 break;
442 case YANG_MODULE:
443 break;
444 case YANG_MUST:
445 break;
446 case YANG_NAMESPACE:
447 break;
448 case YANG_NOTIFICATION:
449 break;
450 case YANG_ORDERED_BY:
451 break;
452 case YANG_ORGANIZATION:
453 break;
454 case YANG_OUTPUT:
455 break;
456 case YANG_PATH:
457 break;
458 case YANG_PATTERN:
459 break;
460 case YANG_POSITION:
461 break;
462 case YANG_PREFIX:
463 break;
464 case YANG_PRESENCE:
465 break;
466 case YANG_RANGE:
467 break;
468 case YANG_REFERENCE:
469 break;
470 case YANG_REFINE:
471 break;
472 case YANG_REQUIRE_INSTANCE:
473 break;
474 case YANG_REVISION:
475 break;
476 case YANG_REVISION_DATE:
477 break;
478 case YANG_RPC:
479 break;
480 case YANG_STATUS:
481 ret = yin_parse_status(xml_ctx, &subelem_attrs, data, subeleme_info_rec->dest, &exts);
482 LY_CHECK_GOTO(ret, cleanup);
483 break;
484 case YANG_SUBMODULE:
485 break;
486 case YANG_TYPE:
487 break;
488 case YANG_TYPEDEF:
489 break;
490 case YANG_UNIQUE:
491 break;
492 case YANG_UNITS:
493 break;
494 case YANG_USES:
495 break;
496 case YANG_VALUE:
497 break;
498 case YANG_WHEN:
499 break;
500 case YANG_YANG_VERSION:
501 break;
502 case YANG_YIN_ELEMENT:
503 break;
504 default:
505 /* TODO specify special */
506 break;
507 }
508 FREE_ARRAY(xml_ctx, subelem_attrs, free_arg_rec);
509 subelem_attrs = NULL;
510 }
511 } else {
512 /* elements with text or none content */
513 /* save text content */
514 /* load closing element */
515 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len));
516 }
517 }
518
519cleanup:
520 FREE_ARRAY(xml_ctx, subelem_attrs, free_arg_rec);
521 return ret;
522}
523
David Sedlák0daba9a2019-03-22 14:07:49 +0100524LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200525yin_parse_text_element(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data, const char **value)
David Sedlák0daba9a2019-03-22 14:07:49 +0100526{
527 LY_ERR ret = LY_SUCCESS;
528 char *buf = NULL, *out = NULL;
David Sedlák15a92662019-06-18 11:55:15 +0200529 const char *prefix = NULL, *name = NULL;
530 size_t buf_len = 0, out_len = 0, prefix_len = 0, name_len = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200531 int dynamic = 0;
David Sedlák0daba9a2019-03-22 14:07:49 +0100532
David Sedlák0daba9a2019-03-22 14:07:49 +0100533 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
534 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
535 LY_CHECK_RET(ret);
David Sedlák57715b12019-06-17 13:05:22 +0200536 if (dynamic) {
537 *value = lydict_insert_zc(xml_ctx->ctx, buf);
David Sedlák00250342019-06-21 14:19:39 +0200538 LY_CHECK_RET(!(*value), LY_EMEM);
David Sedlák57715b12019-06-17 13:05:22 +0200539 } else {
540 *value = lydict_insert(xml_ctx->ctx, out, out_len);
David Sedlák00250342019-06-21 14:19:39 +0200541 LY_CHECK_RET(!(*value), LY_EMEM);
David Sedlák57715b12019-06-17 13:05:22 +0200542 }
David Sedlák0daba9a2019-03-22 14:07:49 +0100543 }
544
David Sedlák00250342019-06-21 14:19:39 +0200545 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
546 /* probably should never happen, mixed content should be caught by lyxml_get_element call but
547 * I will just leave it here for now to be sure */
548 LY_CHECK_RET(name, LY_EVALID);
549 return ret;
David Sedlák15a92662019-06-18 11:55:15 +0200550}
551
David Sedlák00250342019-06-21 14:19:39 +0200552/**
553 * @brief function to parse meta tags eg. elements with text element as child
554 *
555 * @param[in] xml_ctx Xml context.
556 * @param[in] args Sized array of arguments of current elements.
557 * @param[in,out] data Data to read from.
558 * @param[out] value Where the content of meta tag should be stored.
559 *
560 * @return LY_ERR values.
561 */
David Sedlák15a92662019-06-18 11:55:15 +0200562LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200563yin_parse_meta_element(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data, const char **value)
David Sedlák15a92662019-06-18 11:55:15 +0200564{
565 LY_ERR ret = LY_SUCCESS;
566 char *buf = NULL, *out = NULL;
David Sedlák00250342019-06-21 14:19:39 +0200567 const char *prefix = NULL, *name = NULL;
David Sedlák15a92662019-06-18 11:55:15 +0200568 size_t buf_len = 0, out_len = 0, prefix_len = 0, name_len = 0;
569 int dynamic = 0;
David Sedlák15a92662019-06-18 11:55:15 +0200570 enum YIN_ARGUMENT arg = YANG_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200571 struct yin_arg_record *subelem_args = NULL;
572 enum yang_keyword kw = YANG_NONE;
David Sedlák15a92662019-06-18 11:55:15 +0200573
David Sedlák00250342019-06-21 14:19:39 +0200574 LY_CHECK_ERR_RET(xml_ctx->status != LYXML_ELEM_CONTENT, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected content of meta element."), LY_EVALID);
David Sedlák15a92662019-06-18 11:55:15 +0200575
576 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlák00250342019-06-21 14:19:39 +0200577 LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected \"text\" element as first child of meta element."), LY_EINVAL);
David Sedlák15a92662019-06-18 11:55:15 +0200578
David Sedlák8f7a1172019-06-20 14:42:18 +0200579 /* first element should be argument element <text> */
David Sedlák8f7a1172019-06-20 14:42:18 +0200580 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlák00250342019-06-21 14:19:39 +0200581 ret = yin_load_attributes(xml_ctx, data, &subelem_args);
582 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8f7a1172019-06-20 14:42:18 +0200583 arg = yin_match_argument_name(name, name_len);
David Sedlák00250342019-06-21 14:19:39 +0200584 LY_CHECK_ERR_GOTO(arg != YIN_ARG_TEXT, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected \"text\" element as first child of meta element.");
585 ret = LY_EINVAL, cleanup);
586 ret = yin_parse_text_element(xml_ctx, &subelem_args, data, value);
587 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8f7a1172019-06-20 14:42:18 +0200588
David Sedlák15a92662019-06-18 11:55:15 +0200589 /* loop over all child elements and parse them */
590 while (xml_ctx->status == LYXML_ELEMENT) {
David Sedlák00250342019-06-21 14:19:39 +0200591 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
592 LY_CHECK_GOTO(ret, cleanup);
593 ret = yin_load_attributes(xml_ctx, data, &subelem_args);
594 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8f7a1172019-06-20 14:42:18 +0200595 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlák15a92662019-06-18 11:55:15 +0200596
David Sedlák8f7a1172019-06-20 14:42:18 +0200597 if (!name) {
David Sedlák15a92662019-06-18 11:55:15 +0200598 /* end of meta element reached */
599 break;
600 }
601
David Sedlák8f7a1172019-06-20 14:42:18 +0200602 switch (kw) {
603 case YANG_CUSTOM:
604 // TODO parse extension instance
605 break;
606
607 default:
608 LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected child element \"%.*s\".", name_len, name);
609 return LY_EVALID;
610 }
David Sedlák15a92662019-06-18 11:55:15 +0200611 }
612
David Sedlák00250342019-06-21 14:19:39 +0200613cleanup:
614 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
615 return ret;
David Sedlák0daba9a2019-03-22 14:07:49 +0100616}
617
David Sedlák00250342019-06-21 14:19:39 +0200618/**
619 * @brief Parse revision date.
620 *
621 * @param[in] xml_ctx Xml context.
622 * @param[in] args Sized array of arguments of current element.
623 * @param[in,out] data Data to read from.
624 * @param[in,out] rev Array to store the parsed value in.
625 * @param[in,out] exts Extension instances to add to.
626 *
627 * @return LY_ERR values.
628 */
David Sedlák81e04022019-04-05 15:05:46 +0200629static LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200630yin_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 +0200631{
632 LY_ERR ret = LY_SUCCESS;
David Sedlák00250342019-06-21 14:19:39 +0200633 const char *temp_rev, *prefix = NULL, *name = NULL;
634 char *out;
635 struct yin_arg_record *subelem_args = NULL;
636 size_t prefix_len = 0, name_len = 0;
637 enum yang_keyword kw = YANG_NONE;
638 int dynamic;
David Sedlákcd0c9512019-03-29 13:23:06 +0100639
David Sedlák81e04022019-04-05 15:05:46 +0200640 if (rev[0]) {
David Sedlákb3077192019-06-19 10:55:37 +0200641 LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "revision-date");
David Sedlák81e04022019-04-05 15:05:46 +0200642 return LY_EVALID;
643 }
644
David Sedlák8f7a1172019-06-20 14:42:18 +0200645 LY_CHECK_RET(yin_parse_attribute(xml_ctx, args, YIN_ARG_DATE, &temp_rev))
David Sedlák81e04022019-04-05 15:05:46 +0200646 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlákda63c082019-06-04 13:52:23 +0200647 LY_CHECK_RET(lysp_check_date((struct lys_parser_ctx *)xml_ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS, LY_EVALID);
648
649 strcpy(rev, temp_rev);
650 lydict_remove(xml_ctx->ctx, temp_rev);
David Sedlák81e04022019-04-05 15:05:46 +0200651
David Sedlák00250342019-06-21 14:19:39 +0200652 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
653 ret = lyxml_get_string(xml_ctx, data, &out, &name_len, &out, &name_len, &dynamic);
654 /* unknown element text content is ignored */
655 if (ret == LY_EINVAL) {
656 while (xml_ctx->status == LYXML_ELEMENT) {
657 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
658 LY_CHECK_GOTO(ret, cleanup);
659 ret = yin_load_attributes(xml_ctx, data, &subelem_args);
660 LY_CHECK_GOTO(ret, cleanup);
661 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
662
663 if (!name) {
664 /* end of revisin-date element reached */
665 break;
666 }
667
668 switch (kw) {
669 case YANG_CUSTOM:
670 // TODO parse extension instance
671 break;
672
673 default:
674 LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected child element \"%.*s\".", name_len, name);
675 return LY_EVALID;
676 }
677 }
678 } else {
679 /* load closing element */
680 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
681 LY_CHECK_RET(name, LY_EINVAL);
682 }
683 }
684
685cleanup:
686 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
David Sedlák81e04022019-04-05 15:05:46 +0200687 return ret;
688}
David Sedlákcd0c9512019-03-29 13:23:06 +0100689
David Sedlákda63c082019-06-04 13:52:23 +0200690LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200691yin_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 +0100692{
693 LY_ERR ret = LY_SUCCESS;
694 enum yang_keyword kw;
695 struct lysp_import *imp;
696 const char *prefix, *name;
David Sedlák00250342019-06-21 14:19:39 +0200697 char *out;
David Sedlák8f7a1172019-06-20 14:42:18 +0200698 struct yin_arg_record *subelem_args = NULL;
David Sedlák736fd0d2019-02-15 16:06:31 +0100699 size_t prefix_len, name_len;
David Sedlák00250342019-06-21 14:19:39 +0200700 int dynamic;
David Sedlák736fd0d2019-02-15 16:06:31 +0100701
David Sedlák00250342019-06-21 14:19:39 +0200702 /* allocate new element in sized array for import */
David Sedlák8f7a1172019-06-20 14:42:18 +0200703 LY_ARRAY_NEW_GOTO(xml_ctx->ctx, *imports, imp, ret, validation_err);
David Sedlák736fd0d2019-02-15 16:06:31 +0100704
David Sedláka7406952019-04-05 10:33:07 +0200705 /* parse import attributes */
David Sedlák00250342019-06-21 14:19:39 +0200706 LY_CHECK_GOTO(yin_parse_attribute(xml_ctx, import_args, YIN_ARG_MODULE, &imp->name) != LY_SUCCESS, validation_err);
707
708 ret = lyxml_get_string(xml_ctx, data, &out, &name_len, &out, &name_len, &dynamic);
709 LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected new element after import element"), LY_EINVAL);
710
711 while (xml_ctx->status == LYXML_ELEMENT) {
712 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
713 LY_CHECK_GOTO(ret, validation_err);
714 if (!name) {
715 /* end of import element reached */
716 break;
717 }
718 LY_CHECK_GOTO(yin_load_attributes(xml_ctx, data, &subelem_args), validation_err);
David Sedlák8f7a1172019-06-20 14:42:18 +0200719 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlák00250342019-06-21 14:19:39 +0200720
David Sedlák736fd0d2019-02-15 16:06:31 +0100721 switch (kw) {
722 case YANG_PREFIX:
David Sedlák8f7a1172019-06-20 14:42:18 +0200723 LY_CHECK_ERR_GOTO(imp->prefix, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "prefix"), validation_err);
724 LY_CHECK_GOTO(yin_parse_attribute(xml_ctx, &subelem_args, YIN_ARG_VALUE, &imp->prefix) != LY_SUCCESS, validation_err);
725 LY_CHECK_GOTO(lysp_check_prefix((struct lys_parser_ctx *)xml_ctx, *imports, module_prefix, &imp->prefix) != LY_SUCCESS, validation_err);
David Sedlákcd0c9512019-03-29 13:23:06 +0100726 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100727 case YANG_DESCRIPTION:
David Sedlák8f7a1172019-06-20 14:42:18 +0200728 LY_CHECK_ERR_GOTO(imp->dsc, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "description"), validation_err);
David Sedlák00250342019-06-21 14:19:39 +0200729 LY_CHECK_GOTO(yin_parse_meta_element(xml_ctx, &subelem_args, data, &imp->dsc), validation_err);
David Sedlákcd0c9512019-03-29 13:23:06 +0100730 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100731 case YANG_REFERENCE:
David Sedlák8f7a1172019-06-20 14:42:18 +0200732 LY_CHECK_ERR_GOTO(imp->ref, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "reference"), validation_err);
David Sedlák00250342019-06-21 14:19:39 +0200733 LY_CHECK_GOTO(yin_parse_meta_element(xml_ctx, &subelem_args, data, &imp->ref), validation_err);
David Sedlákcd0c9512019-03-29 13:23:06 +0100734 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100735 case YANG_REVISION_DATE:
David Sedlák00250342019-06-21 14:19:39 +0200736 LY_CHECK_GOTO(yin_parse_revision_date(xml_ctx, &subelem_args, data, imp->rev, &imp->exts), validation_err);
David Sedlák3a55bc12019-06-03 08:57:29 +0200737 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100738 case YANG_CUSTOM:
739 /* TODO parse extension */
David Sedlák3a55bc12019-06-03 08:57:29 +0200740 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100741 default:
David Sedlák916b1902019-06-06 11:35:05 +0200742 LOGERR(xml_ctx->ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, "import");
David Sedlák8f7a1172019-06-20 14:42:18 +0200743 goto validation_err;
David Sedlák736fd0d2019-02-15 16:06:31 +0100744 }
David Sedlák4af209e2019-06-21 14:24:50 +0200745 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
David Sedlák8f7a1172019-06-20 14:42:18 +0200746 subelem_args = NULL;
David Sedlák736fd0d2019-02-15 16:06:31 +0100747 }
748
David Sedlák8f7a1172019-06-20 14:42:18 +0200749 LY_CHECK_ERR_GOTO(!imp->prefix, LOGVAL_PARSER(xml_ctx, LY_VCODE_MISSATTR, "prefix", "import"), validation_err);
David Sedlák736fd0d2019-02-15 16:06:31 +0100750 return ret;
David Sedlák8f7a1172019-06-20 14:42:18 +0200751
752validation_err:
David Sedlák4af209e2019-06-21 14:24:50 +0200753 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
David Sedlák8f7a1172019-06-20 14:42:18 +0200754 return LY_EVALID;
David Sedlák736fd0d2019-02-15 16:06:31 +0100755}
756
David Sedlák11900c82019-06-18 16:29:12 +0200757LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200758yin_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 +0200759{
760 LY_ERR ret = LY_SUCCESS;
761 enum yang_keyword kw = YANG_NONE;
762 const char *value = NULL, *prefix = NULL, *name = NULL;
763 char *out;
764 size_t prefix_len = 0, name_len = 0, out_len = 0;
765 int dynamic = 0;
David Sedlák00250342019-06-21 14:19:39 +0200766 struct yin_arg_record *subelem_args = NULL;
David Sedlák11900c82019-06-18 16:29:12 +0200767 if (*flags & LYS_STATUS_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +0200768 LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPELEM, "status");
David Sedlák11900c82019-06-18 16:29:12 +0200769 return LY_EVALID;
770 }
771
David Sedlák8f7a1172019-06-20 14:42:18 +0200772 LY_CHECK_RET(yin_parse_attribute(xml_ctx, status_args, YIN_ARG_VALUE, &value));
David Sedlák11900c82019-06-18 16:29:12 +0200773 if (strcmp(value, "current") == 0) {
774 *flags |= LYS_STATUS_CURR;
775 } else if (strcmp(value, "deprecated") == 0) {
776 *flags |= LYS_STATUS_DEPRC;
777 } else if (strcmp(value, "obsolete") == 0) {
778 *flags |= LYS_STATUS_OBSLT;
779 } else {
David Sedlákb3077192019-06-19 10:55:37 +0200780 LOGVAL_PARSER(xml_ctx, LY_VCODE_INVAL_YIN, value, "status");
David Sedlák11900c82019-06-18 16:29:12 +0200781 lydict_remove(xml_ctx->ctx, value);
782 return LY_EVALID;
783 }
784 lydict_remove(xml_ctx->ctx, value);
785
David Sedlákb6e65972019-06-19 10:44:13 +0200786 /* TODO check if dynamic was set to 1 in case of error */
787 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
788 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
789 /* if there are any xml subelements parse them, unknown text content is silently ignored */
790 if (ret == LY_EINVAL) {
791 /* load subelements */
792 while (xml_ctx->status == LYXML_ELEMENT) {
793 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
794 if (!name) {
David Sedlák00250342019-06-21 14:19:39 +0200795 /* end of status reached */
David Sedlákb6e65972019-06-19 10:44:13 +0200796 break;
797 }
David Sedlák00250342019-06-21 14:19:39 +0200798 ret = yin_load_attributes(xml_ctx, data, &subelem_args);
799 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8f7a1172019-06-20 14:42:18 +0200800 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlákb6e65972019-06-19 10:44:13 +0200801 switch (kw) {
802 case YANG_CUSTOM:
803 /* TODO parse extension instance */
804 break;
805 default:
David Sedlákb3077192019-06-19 10:55:37 +0200806 LOGVAL_PARSER(xml_ctx, LY_VCODE_INCHILDSTMT_YIN, name_len, name, 6, "status");
David Sedlák00250342019-06-21 14:19:39 +0200807 ret = LY_EVALID;
808 goto cleanup;
David Sedlákb6e65972019-06-19 10:44:13 +0200809 }
David Sedlák00250342019-06-21 14:19:39 +0200810
811 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
812 subelem_args = NULL;
David Sedlákb6e65972019-06-19 10:44:13 +0200813 }
David Sedlák00250342019-06-21 14:19:39 +0200814 } else {
815 /* load closing element */
816 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
817 LY_CHECK_RET(name, LY_EINVAL);
David Sedlák11900c82019-06-18 16:29:12 +0200818 }
819 }
820
821 return ret;
David Sedlák00250342019-06-21 14:19:39 +0200822
823cleanup:
824 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
825 return ret;
David Sedlák11900c82019-06-18 16:29:12 +0200826}
827
David Sedlák11900c82019-06-18 16:29:12 +0200828LY_ERR
David Sedlák2721d3d2019-06-21 15:37:41 +0200829yin_parse_yin_element_element(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data, uint16_t *flags, struct lysp_ext **extensions)
830{
831 LY_ERR ret = LY_SUCCESS;
David Sedlák2453f9d2019-06-27 15:59:04 +0200832 const char *temp_val = NULL, *name = NULL;
833 size_t name_len = 0;
David Sedlák2721d3d2019-06-21 15:37:41 +0200834 struct yin_arg_record *subelem_args = NULL;
David Sedlák2721d3d2019-06-21 15:37:41 +0200835 enum yang_keyword kw = YANG_NONE;
David Sedlák9bc65872019-06-24 20:21:08 +0200836 struct yin_arg_record temp_record;
David Sedlák2721d3d2019-06-21 15:37:41 +0200837
838 if (*flags & LYS_YINELEM_MASK) {
839 LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "yin-element");
840 return LY_EVALID;
841 }
842
843 LY_CHECK_RET(yin_parse_attribute(xml_ctx, attrs, YIN_ARG_VALUE, &temp_val));
844 if (strcmp(temp_val, "true") == 0) {
845 *flags |= LYS_YINELEM_TRUE;
846 } else if (strcmp(temp_val, "false") == 0) {
847 *flags |= LYS_YINELEM_FALSE;
848 } else {
849 LOGVAL_PARSER(xml_ctx, LY_VCODE_INVAL_YIN, temp_val, "yin-element");
850 lydict_remove(xml_ctx->ctx, temp_val);
851 return LY_EVALID;
852 }
853 lydict_remove(xml_ctx->ctx, temp_val);
854
David Sedlák9bc65872019-06-24 20:21:08 +0200855 YIN_READ_SUBELEMS_START(xml_ctx, data, ret, cleanup, kw, temp_record, subelem_args);
David Sedlák9bc65872019-06-24 20:21:08 +0200856 switch (kw) {
857 case YANG_CUSTOM:
858 // TODO parse extension instance
859 break;
860
861 default:
862 LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected child element \"%.*s\".", name_len, name);
863 return LY_EVALID;
864 }
865 YIN_READ_SUBELEMS_END(xml_ctx, data, temp_record);
David Sedlák2721d3d2019-06-21 15:37:41 +0200866
867cleanup:
868 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
869 return ret;
870}
871
872LY_ERR
David Sedlák1e2cdd02019-06-27 14:17:43 +0200873yin_parse_extension_instance(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data,
874 const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
875 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
876{
877 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +0200878 char *out;
879 const char *name, *prefix;
880 size_t out_len, prefix_len, name_len;
881 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +0200882 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +0200883 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
884 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +0200885
886 LY_ARRAY_NEW_RET(xml_ctx->ctx, *exts, e, LY_EMEM);
887
888 e->yin = 0;
889 /* store name and insubstmt info */
890 e->name = lydict_insert(xml_ctx->ctx, ext_name, ext_name_len);
891 e->insubstmt = insubstmt;
892 e->insubstmt_index = insubstmt_index;
893 e->yin |= LYS_YIN;
894
David Sedlákb1a78352019-06-28 16:16:29 +0200895 /* store attributes as subelements */
896 LY_ARRAY_FOR_ITER(*attrs, struct yin_arg_record, iter) {
897 if (!iter->prefix) {
898 new_subelem = calloc(1, sizeof(*new_subelem));
899 if (!e->child) {
900 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +0200901 } else {
David Sedlákb1a78352019-06-28 16:16:29 +0200902 last_subelem->next = new_subelem;
903 }
904 last_subelem = new_subelem;
905
906 last_subelem->flags |= LYS_YIN_ATTR;
907 last_subelem->stmt = lydict_insert(xml_ctx->ctx, iter->name, iter->name_len);
908 LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(xml_ctx->ctx), LY_EMEM);
909 if (iter->dynamic_content) {
910 last_subelem->arg = lydict_insert_zc(xml_ctx->ctx, iter->content);
911 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(xml_ctx->ctx), LY_EMEM);
912 } else {
913 last_subelem->arg = lydict_insert(xml_ctx->ctx, iter->content, iter->content_len);
914 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(xml_ctx->ctx), LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +0200915 }
916 }
917 }
David Sedlák1e2cdd02019-06-27 14:17:43 +0200918
David Sedlákf250ecf2019-07-01 11:02:05 +0200919 /* parse subelements */
David Sedlákb1a78352019-06-28 16:16:29 +0200920 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
921 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
922 if (ret == LY_EINVAL) {
923 while (xml_ctx->status == LYXML_ELEMENT) {
924 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
925 if (!name) {
926 /* end of extension instance reached */
927 break;
928 }
David Sedlákf250ecf2019-07-01 11:02:05 +0200929 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 +0200930 if (!e->child) {
931 e->child = new_subelem;
932 } else {
933 last_subelem->next = new_subelem;
934 }
935 last_subelem = new_subelem;
936 }
937 }
938 } else {
939 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
940 LY_CHECK_RET(name, LY_EINVAL);
941 }
942
943 return LY_SUCCESS;
944}
945
946LY_ERR
David Sedlákf250ecf2019-07-01 11:02:05 +0200947yin_parse_element_generic(struct lyxml_context *xml_ctx, const char *name, size_t name_len, const char *prefix,
948 size_t prefix_len, const char **data, struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +0200949{
950 LY_ERR ret = LY_SUCCESS;
951 const char *temp_prefix, *temp_name;
952 char *out = NULL;
David Sedlákf250ecf2019-07-01 11:02:05 +0200953 size_t out_len, temp_name_len, temp_prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +0200954 int dynamic;
955 struct yin_arg_record *subelem_args = NULL;
956 struct lysp_stmt *last = NULL, *new = NULL;
957
958 /* allocate new structure for element */
959 *element = calloc(1, sizeof(**element));
960 (*element)->stmt = lydict_insert(xml_ctx->ctx, name, name_len);
961 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(xml_ctx->ctx), LY_EMEM);
962
963 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +0200964 /* load attributes */
David Sedlákb1a78352019-06-28 16:16:29 +0200965 while(xml_ctx->status == LYXML_ATTRIBUTE) {
966 /* add new element to linked-list */
967 new = calloc(1, sizeof(*last));
968 LY_CHECK_ERR_GOTO(ret, LOGMEM(xml_ctx->ctx), err);
969 if (!(*element)->child) {
970 /* save first */
971 (*element)->child = new;
972 } else {
973 last->next = new;
974 }
975 last = new;
976
977 last->flags |= LYS_YIN_ATTR;
978 ret = lyxml_get_attribute(xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
979 LY_CHECK_GOTO(ret, err);
980 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
981 LY_CHECK_GOTO(ret, err);
982 last->stmt = lydict_insert(xml_ctx->ctx, temp_name, temp_name_len);
983 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(xml_ctx->ctx); ret = LY_EMEM, err);
984 /* attributes with prefix are ignored */
985 if (!temp_prefix) {
986 if (dynamic) {
987 last->arg = lydict_insert_zc(xml_ctx->ctx, out);
988 if (!last->arg) {
989 free(out);
990 LOGMEM(xml_ctx->ctx);
991 ret = LY_EMEM;
992 goto err;
993 }
994 } else {
995 last->arg = lydict_insert(xml_ctx->ctx, out, out_len);
996 LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(xml_ctx->ctx); ret = LY_EMEM, err);
997 }
998 }
999 }
1000
1001 /* parse content of element */
1002 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
1003 if (ret == LY_EINVAL) {
1004 while (xml_ctx->status == LYXML_ELEMENT) {
1005 /* parse subelements */
David Sedlákf250ecf2019-07-01 11:02:05 +02001006 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 +02001007 LY_CHECK_GOTO(ret, err);
1008 if (!name) {
1009 /* end of element reached */
1010 break;
1011 }
David Sedlákf250ecf2019-07-01 11:02:05 +02001012 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 +02001013 LY_CHECK_GOTO(ret, err);
1014 last = last->next;
1015 }
1016 } else {
1017 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +02001018 if (out_len != 0) {
1019 if (dynamic) {
1020 (*element)->arg = lydict_insert_zc(xml_ctx->ctx, out);
1021 if (!(*element)->arg) {
1022 free(out);
1023 LOGMEM(xml_ctx->ctx);
1024 ret = LY_EMEM;
1025 goto err;
1026 }
1027 } else {
1028 (*element)->arg = lydict_insert(xml_ctx->ctx, out, out_len);
1029 LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(xml_ctx->ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02001030 }
David Sedlákb1a78352019-06-28 16:16:29 +02001031 }
1032 /* read closing tag */
1033 ret = lyxml_get_element(xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
1034 LY_CHECK_GOTO(ret, err);
1035 }
1036
1037 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
1038 return LY_SUCCESS;
1039
1040err:
1041 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +02001042 return ret;
1043}
1044
1045LY_ERR
David Sedlák9494eb22019-06-21 16:06:53 +02001046yin_parse_argument_element(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data,
1047 uint16_t *flags, const char **argument, struct lysp_ext **extensions)
1048{
1049 LY_ERR ret = LY_SUCCESS;
David Sedlák2453f9d2019-06-27 15:59:04 +02001050 const char *name = NULL;
1051 size_t name_len = 0;
David Sedlák9494eb22019-06-21 16:06:53 +02001052 struct yin_arg_record *subelem_args = NULL;
David Sedlák9494eb22019-06-21 16:06:53 +02001053 enum yang_keyword kw = YANG_NONE;
David Sedlák9bc65872019-06-24 20:21:08 +02001054 struct yin_arg_record temp_record;
David Sedlák9494eb22019-06-21 16:06:53 +02001055
1056 LY_CHECK_RET(yin_parse_attribute(xml_ctx, attrs, YIN_ARG_NAME, argument));
1057
David Sedlák9bc65872019-06-24 20:21:08 +02001058 YIN_READ_SUBELEMS_START(xml_ctx, data, ret, cleanup, kw, temp_record, subelem_args);
1059 if (!name) {
1060 /* end of argument element reached */
1061 break;
David Sedlák9494eb22019-06-21 16:06:53 +02001062 }
David Sedlák9bc65872019-06-24 20:21:08 +02001063
1064 switch (kw) {
1065 case YANG_YIN_ELEMENT:
1066 yin_parse_yin_element_element(xml_ctx, &subelem_args, data, flags, extensions);
1067 break;
1068 case YANG_CUSTOM:
1069 // TODO parse extension instance
1070 break;
1071
1072 default:
1073 LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected child element \"%.*s\".", name_len, name);
1074 return LY_EVALID;
1075 }
1076 YIN_READ_SUBELEMS_END(xml_ctx, data, temp_record);
David Sedlák9494eb22019-06-21 16:06:53 +02001077
1078cleanup:
1079 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
1080 return ret;
1081}
1082
1083LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +02001084yin_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 +02001085{
1086 LY_ERR ret = LY_SUCCESS;
1087 struct lysp_ext *ex;
1088 const char *prefix = NULL, *name = NULL;
1089 char *out = NULL;
1090 size_t out_len = 0, prefix_len = 0, name_len = 0;
1091 int dynamic = 0;
1092 enum yang_keyword kw = YANG_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +02001093 struct yin_arg_record *subelem_args = NULL;
David Sedlák11900c82019-06-18 16:29:12 +02001094
David Sedlák00250342019-06-21 14:19:39 +02001095 LY_ARRAY_NEW_GOTO(xml_ctx->ctx, *extensions, ex, ret, cleanup);
1096 ret = yin_parse_attribute(xml_ctx, extension_args, YIN_ARG_NAME, &ex->name);
1097 LY_CHECK_GOTO(ret, cleanup);
David Sedlák11900c82019-06-18 16:29:12 +02001098 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlák00250342019-06-21 14:19:39 +02001099 LY_CHECK_ERR_GOTO(ret != LY_EINVAL, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected new element after extension element.");
1100 ret = LY_EINVAL, cleanup);
David Sedlák11900c82019-06-18 16:29:12 +02001101
1102 while (xml_ctx->status == LYXML_ELEMENT) {
1103 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02001104 LY_CHECK_GOTO(ret, cleanup);
David Sedlák11900c82019-06-18 16:29:12 +02001105 if (!name) {
David Sedlák00250342019-06-21 14:19:39 +02001106 /* end of extension element reached */
David Sedlák11900c82019-06-18 16:29:12 +02001107 break;
1108 }
David Sedlák00250342019-06-21 14:19:39 +02001109 ret = yin_load_attributes(xml_ctx, data, &subelem_args);
1110 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8f7a1172019-06-20 14:42:18 +02001111 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlák11900c82019-06-18 16:29:12 +02001112 switch (kw) {
1113 case YANG_ARGUMENT:
David Sedlák9494eb22019-06-21 16:06:53 +02001114 ret = yin_parse_argument_element(xml_ctx, &subelem_args, data, &ex->flags, &ex->argument, extensions);
David Sedlák11900c82019-06-18 16:29:12 +02001115 break;
1116 case YANG_DESCRIPTION:
David Sedlák00250342019-06-21 14:19:39 +02001117 ret = yin_parse_meta_element(xml_ctx, &subelem_args, data, &ex->dsc);
1118 LY_CHECK_GOTO(ret, cleanup);
David Sedlák11900c82019-06-18 16:29:12 +02001119 break;
1120 case YANG_REFERENCE:
David Sedlák00250342019-06-21 14:19:39 +02001121 ret = yin_parse_meta_element(xml_ctx, &subelem_args, data, &ex->ref);
1122 LY_CHECK_GOTO(ret, cleanup);
David Sedlák11900c82019-06-18 16:29:12 +02001123 break;
1124 case YANG_STATUS:
David Sedlák00250342019-06-21 14:19:39 +02001125 ret = yin_parse_status(xml_ctx, &subelem_args, data, &ex->flags, &ex->exts);
1126 LY_CHECK_GOTO(ret, cleanup);
David Sedlák11900c82019-06-18 16:29:12 +02001127 break;
1128 case YANG_CUSTOM:
1129 /* TODO parse extension instance */
1130 break;
1131 default:
David Sedlákb3077192019-06-19 10:55:37 +02001132 LOGVAL_PARSER(xml_ctx, LY_VCODE_INCHILDSTMT_YIN, name_len, name, 9, "extension");
David Sedlák00250342019-06-21 14:19:39 +02001133 ret = LY_EVALID;
1134 goto cleanup;
David Sedlák11900c82019-06-18 16:29:12 +02001135 }
David Sedlák00250342019-06-21 14:19:39 +02001136 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
David Sedlák288c1472019-06-20 16:09:48 +02001137 subelem_args = NULL;
David Sedlák11900c82019-06-18 16:29:12 +02001138 }
1139
David Sedlák00250342019-06-21 14:19:39 +02001140cleanup:
1141 FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
David Sedlák11900c82019-06-18 16:29:12 +02001142 return ret;
1143}
1144
David Sedlák00250342019-06-21 14:19:39 +02001145/**
1146 * @brief Parse module substatements.
1147 *
1148 * @param[in] xml_ctx Xml context.
1149 * @param[in,out] data Data to read from.
1150 * @param[out] mod Parsed module structure.
1151 *
1152 * @return LY_ERR values.
1153 */
1154LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +02001155yin_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 +02001156{
David Sedlákf3b24f62018-11-02 10:40:47 +01001157 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +01001158 enum yang_keyword kw = YANG_NONE;
David Sedláke4889912018-11-02 09:52:40 +01001159 const char *prefix, *name;
David Sedlák3b4db242018-10-19 16:11:01 +02001160 size_t prefix_len, name_len;
David Sedlák4b4713f2019-02-15 13:47:45 +01001161 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
David Sedlák3b4db242018-10-19 16:11:01 +02001162
David Sedlákf3b24f62018-11-02 10:40:47 +01001163 char *buf = NULL, *out = NULL;
1164 size_t buf_len = 0, out_len = 0;
David Sedlák57715b12019-06-17 13:05:22 +02001165 int dynamic = 0;
David Sedlák8f7a1172019-06-20 14:42:18 +02001166 struct yin_arg_record *substmt_args = NULL;
David Sedlákf3b24f62018-11-02 10:40:47 +01001167
David Sedlák8f7a1172019-06-20 14:42:18 +02001168 yin_parse_attribute(xml_ctx, mod_args, YIN_ARG_NAME, &(*mod)->mod->name);
David Sedlákb3077192019-06-19 10:55:37 +02001169 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 +01001170 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlákb3077192019-06-19 10:55:37 +02001171 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 +01001172
David Sedlák736fd0d2019-02-15 16:06:31 +01001173 /* loop over all elements and parse them */
David Sedlákc136b972019-03-08 13:39:06 +01001174 while (xml_ctx->status != LYXML_END) {
David Sedlák4b4713f2019-02-15 13:47:45 +01001175#define CHECK_ORDER(SECTION) \
1176 if (mod_stmt > SECTION) {return LY_EVALID;}mod_stmt = SECTION
1177
1178 switch (kw) {
1179 /* module header */
1180 case YANG_NAMESPACE:
1181 case YANG_PREFIX:
1182 CHECK_ORDER(Y_MOD_MODULE_HEADER);
1183 break;
1184 case YANG_YANG_VERSION:
1185 CHECK_ORDER(Y_MOD_MODULE_HEADER);
1186 break;
1187 /* linkage */
1188 case YANG_INCLUDE:
1189 case YANG_IMPORT:
1190 CHECK_ORDER(Y_MOD_LINKAGE);
1191 break;
1192 /* meta */
1193 case YANG_ORGANIZATION:
1194 case YANG_CONTACT:
1195 case YANG_DESCRIPTION:
1196 case YANG_REFERENCE:
1197 CHECK_ORDER(Y_MOD_META);
1198 break;
1199
1200 /* revision */
1201 case YANG_REVISION:
1202 CHECK_ORDER(Y_MOD_REVISION);
1203 break;
1204 /* body */
1205 case YANG_ANYDATA:
1206 case YANG_ANYXML:
1207 case YANG_AUGMENT:
1208 case YANG_CHOICE:
1209 case YANG_CONTAINER:
1210 case YANG_DEVIATION:
1211 case YANG_EXTENSION:
1212 case YANG_FEATURE:
1213 case YANG_GROUPING:
1214 case YANG_IDENTITY:
1215 case YANG_LEAF:
1216 case YANG_LEAF_LIST:
1217 case YANG_LIST:
1218 case YANG_NOTIFICATION:
1219 case YANG_RPC:
1220 case YANG_TYPEDEF:
1221 case YANG_USES:
1222 case YANG_CUSTOM:
1223 mod_stmt = Y_MOD_BODY;
1224 break;
1225 default:
1226 /* error will be handled in the next switch */
1227 break;
1228 }
1229#undef CHECK_ORDER
1230
David Sedlák68826732019-06-05 10:50:58 +02001231 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákc136b972019-03-08 13:39:06 +01001232 if (name) {
David Sedlák8f7a1172019-06-20 14:42:18 +02001233 LY_CHECK_RET(yin_load_attributes(xml_ctx, data, &substmt_args));
1234 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlákc136b972019-03-08 13:39:06 +01001235 switch (kw) {
David Sedlák736fd0d2019-02-15 16:06:31 +01001236
David Sedlákc136b972019-03-08 13:39:06 +01001237 /* module header */
1238 case YANG_NAMESPACE:
David Sedlák00250342019-06-21 14:19:39 +02001239 ret = yin_parse_attribute(xml_ctx, &substmt_args, YIN_ARG_URI, &(*mod)->mod->ns);
1240 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +01001241 break;
1242 case YANG_PREFIX:
David Sedlák00250342019-06-21 14:19:39 +02001243 ret = yin_parse_attribute(xml_ctx, &substmt_args, YIN_ARG_VALUE, &(*mod)->mod->prefix);
1244 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +01001245 break;
David Sedlák4a4c0722018-11-26 17:03:10 +01001246
David Sedlákc136b972019-03-08 13:39:06 +01001247 /* linkage */
1248 case YANG_IMPORT:
David Sedlák00250342019-06-21 14:19:39 +02001249 ret = yin_parse_import(xml_ctx, &substmt_args, (*mod)->mod->prefix, data, &(*mod)->imports);
1250 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +01001251 break;
David Sedlák736fd0d2019-02-15 16:06:31 +01001252
David Sedlákc136b972019-03-08 13:39:06 +01001253 /* meta */
1254 case YANG_ORGANIZATION:
David Sedlák00250342019-06-21 14:19:39 +02001255 ret = yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->org);
1256 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +01001257 break;
1258 case YANG_CONTACT:
David Sedlák00250342019-06-21 14:19:39 +02001259 ret = yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->contact);
1260 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +01001261 break;
1262 case YANG_DESCRIPTION:
David Sedlák00250342019-06-21 14:19:39 +02001263 ret = yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->dsc);
1264 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +01001265 break;
1266 case YANG_REFERENCE:
David Sedlák00250342019-06-21 14:19:39 +02001267 ret = yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->ref);
1268 LY_CHECK_GOTO(ret, error);
David Sedlákc136b972019-03-08 13:39:06 +01001269 break;
David Sedlák11900c82019-06-18 16:29:12 +02001270 /* revision */
1271
1272 /*body */
1273 case YANG_EXTENSION:
David Sedlák00250342019-06-21 14:19:39 +02001274 ret = yin_parse_extension(xml_ctx, &substmt_args, data, &(*mod)->extensions);
1275 LY_CHECK_GOTO(ret, error);
David Sedlák11900c82019-06-18 16:29:12 +02001276 break;
David Sedlák736fd0d2019-02-15 16:06:31 +01001277
David Sedlákc136b972019-03-08 13:39:06 +01001278 default:
David Sedlák00250342019-06-21 14:19:39 +02001279 ret = LY_EVALID;
1280 goto error;
David Sedlákc136b972019-03-08 13:39:06 +01001281 }
David Sedlák00250342019-06-21 14:19:39 +02001282 FREE_ARRAY(xml_ctx, substmt_args, free_arg_rec);
David Sedlák8f7a1172019-06-20 14:42:18 +02001283 substmt_args = NULL;
David Sedlák4a4c0722018-11-26 17:03:10 +01001284 }
1285 }
1286
David Sedlák68826732019-06-05 10:50:58 +02001287 return LY_SUCCESS;
David Sedlák00250342019-06-21 14:19:39 +02001288
1289error:
1290 FREE_ARRAY(xml_ctx, substmt_args, free_arg_rec);
1291 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02001292}
1293
1294LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +01001295yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02001296{
David Sedláke4889912018-11-02 09:52:40 +01001297 LY_ERR ret = LY_SUCCESS;
1298 enum yang_keyword kw = YANG_NONE;
David Sedlákecf5eb82019-06-03 14:12:44 +02001299 struct lys_parser_ctx parser_ctx;
David Sedlákaadab9c2019-04-05 15:01:27 +02001300 struct lyxml_context *xml_ctx = (struct lyxml_context *)&parser_ctx;
David Sedlák3017da42019-02-15 09:48:04 +01001301 struct lysp_module *mod_p = NULL;
1302 const char *prefix, *name;
1303 size_t prefix_len, name_len;
David Sedlák8f7a1172019-06-20 14:42:18 +02001304 struct yin_arg_record *args = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02001305
David Sedlák3017da42019-02-15 09:48:04 +01001306 /* initialize xml context */
David Sedlákaadab9c2019-04-05 15:01:27 +02001307 memset(&parser_ctx, 0, sizeof parser_ctx);
1308 xml_ctx->ctx = ctx;
1309 xml_ctx->line = 1;
David Sedláke4889912018-11-02 09:52:40 +01001310
David Sedlák3017da42019-02-15 09:48:04 +01001311 /* check submodule */
David Sedlákaadab9c2019-04-05 15:01:27 +02001312 ret = lyxml_get_element(xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02001313 LY_CHECK_GOTO(ret, cleanup);
1314 ret = yin_load_attributes(xml_ctx, &data, &args);
1315 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8f7a1172019-06-20 14:42:18 +02001316 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedláke4889912018-11-02 09:52:40 +01001317 if (kw == YANG_SUBMODULE) {
David Sedlák3017da42019-02-15 09:48:04 +01001318 LOGERR(ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
1319 ret = LY_EINVAL;
1320 goto cleanup;
1321 } else if (kw != YANG_MODULE) {
David Sedlákb3077192019-06-19 10:55:37 +02001322 LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
David Sedlák79e50cb2019-06-05 16:33:09 +02001323 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01001324 ret = LY_EVALID;
1325 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01001326 }
1327
David Sedlák3017da42019-02-15 09:48:04 +01001328 /* allocate module */
1329 mod_p = calloc(1, sizeof *mod_p);
1330 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
1331 mod_p->mod = mod;
1332 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01001333
David Sedlák00250342019-06-21 14:19:39 +02001334 /* parse module substatements */
David Sedlák8f7a1172019-06-20 14:42:18 +02001335 ret = yin_parse_mod(xml_ctx, &args, &data, &mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01001336 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01001337
David Sedlák3017da42019-02-15 09:48:04 +01001338 mod_p->parsing = 0;
1339 mod->parsed = mod_p;
1340
1341cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02001342 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01001343 lysp_module_free(mod_p);
1344 }
David Sedlák00250342019-06-21 14:19:39 +02001345 FREE_ARRAY(xml_ctx, args, free_arg_rec);
David Sedlákaadab9c2019-04-05 15:01:27 +02001346 lyxml_context_clear(xml_ctx);
David Sedlák2e411422018-12-17 02:35:39 +01001347 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02001348}