blob: 38ffbb18759b4fd0b168c5f7be300409b3f9f845 [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ák5545f5d2019-07-11 11:55:16 +020022#include <errno.h>
David Sedlákf75d55e2019-07-12 16:52:50 +020023#include <ctype.h>
David Sedlák81497a32019-08-13 16:56:26 +020024#include <stdarg.h>
David Sedlákf824ad52018-10-14 23:58:15 +020025
David Sedlákf824ad52018-10-14 23:58:15 +020026#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020027#include "dict.h"
David Sedlák3b4db242018-10-19 16:11:01 +020028#include "xml.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020029#include "tree.h"
30#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020031#include "tree_schema_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020032#include "parser_yin.h"
David Sedlák00250342019-06-21 14:19:39 +020033
David Sedlák2b214ac2019-06-06 16:11:03 +020034/**
35 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020036 *
David Sedlák2b214ac2019-06-06 16:11:03 +020037 * @param ns Namespace URI to check.
38 *
39 * @return true if ns equals YIN_NS_URI false otherwise.
40 */
41#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
42
David Sedlákf6251182019-06-06 10:22:13 +020043const char *const yin_attr_list[] = {
44 [YIN_ARG_NAME] = "name",
45 [YIN_ARG_TARGET_NODE] = "target-node",
46 [YIN_ARG_MODULE] = "module",
47 [YIN_ARG_VALUE] = "value",
48 [YIN_ARG_TEXT] = "text",
49 [YIN_ARG_CONDITION] = "condition",
50 [YIN_ARG_URI] = "uri",
51 [YIN_ARG_DATE] = "date",
52 [YIN_ARG_TAG] = "tag",
David Sedlákf6251182019-06-06 10:22:13 +020053};
54
David Sedlák1bccdfa2019-06-17 15:55:27 +020055enum yang_keyword
David Sedlákc1771b12019-07-10 15:55:46 +020056yin_match_keyword(struct yin_parser_ctx *ctx, const char *name, size_t name_len,
57 const char *prefix, size_t prefix_len, enum yang_keyword parrent)
David Sedlák1bccdfa2019-06-17 15:55:27 +020058{
David Sedlák8f7a1172019-06-20 14:42:18 +020059 const char *start = NULL;
60 enum yang_keyword kw = YANG_NONE;
61 const struct lyxml_ns *ns = NULL;
62
63 if (!name || name_len == 0) {
David Sedlák1bccdfa2019-06-17 15:55:27 +020064 return YANG_NONE;
65 }
66
David Sedlákda8ffa32019-07-08 14:17:10 +020067 ns = lyxml_ns_get(&ctx->xml_ctx, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +020068 if (ns) {
69 if (!IS_YIN_NS(ns->uri)) {
70 return YANG_CUSTOM;
71 }
72 } else {
73 /* elements without namespace are automatically unknown */
74 return YANG_NONE;
75 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020076
David Sedlák8f7a1172019-06-20 14:42:18 +020077 start = name;
78 kw = lysp_match_kw(NULL, &name);
79
80 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +020081 /* this is done because of collision in yang statement value and yang argument mapped to yin element value */
82 if (kw == YANG_VALUE && parrent == YANG_ERROR_MESSAGE) {
83 return YIN_VALUE;
84 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020085 return kw;
86 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020087 if (strncmp(start, "text", name_len) == 0) {
88 return YIN_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +020089 } else {
90 return YANG_NONE;
91 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020092 }
93}
94
David Sedlákc5b20842019-08-13 10:18:31 +020095enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +020096yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020097{
David Sedlákc5b20842019-08-13 10:18:31 +020098 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +020099 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200100 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200101
David Sedlák94de2aa2019-02-15 12:42:11 +0100102#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
103#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100104#define IF_ARG_PREFIX_END }
105
David Sedlák1c8b2702019-02-22 11:03:02 +0100106 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100107 case 'c':
108 already_read += 1;
109 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200110 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200111
David Sedlák94de2aa2019-02-15 12:42:11 +0100112 case 'd':
113 already_read += 1;
114 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200115 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200116
David Sedlák94de2aa2019-02-15 12:42:11 +0100117 case 'm':
118 already_read += 1;
119 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200120 break;
121
David Sedlák94de2aa2019-02-15 12:42:11 +0100122 case 'n':
123 already_read += 1;
124 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200125 break;
126
David Sedlák94de2aa2019-02-15 12:42:11 +0100127 case 't':
128 already_read += 1;
129 IF_ARG_PREFIX("a", 1)
130 IF_ARG("g", 1, YIN_ARG_TAG)
131 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
132 IF_ARG_PREFIX_END
133 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200134 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200135
David Sedlák94de2aa2019-02-15 12:42:11 +0100136 case 'u':
137 already_read += 1;
138 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200139 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200140
David Sedlák94de2aa2019-02-15 12:42:11 +0100141 case 'v':
142 already_read += 1;
143 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200144 break;
145 }
146
David Sedlákc10e7902018-12-17 02:17:59 +0100147 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200148 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200149 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200150 }
151
David Sedlák18730132019-03-15 15:51:34 +0100152#undef IF_ARG
153#undef IF_ARG_PREFIX
154#undef IF_ARG_PREFIX_END
155
David Sedlák872c7b42018-10-26 13:15:20 +0200156 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200157}
158
David Sedlák4f03b932019-07-26 13:01:47 +0200159void free_arg_rec(struct yin_parser_ctx *ctx, struct yin_arg_record *record) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200160 (void)ctx; /* unused */
David Sedlákd2d676a2019-07-22 11:28:19 +0200161 if (record && record->dynamic_content) {
David Sedlák00250342019-06-21 14:19:39 +0200162 free(record->content);
163 }
164}
165
David Sedlák81497a32019-08-13 16:56:26 +0200166#define IS_NODE_ELEM(kw) (kw == YANG_ANYXML || kw == YANG_ANYDATA || kw == YANG_LEAF || kw == YANG_LEAF_LIST || \
167 kw == YANG_TYPEDEF || kw == YANG_USES || kw == YANG_LIST || kw == YANG_NOTIFICATION || \
168 kw == YANG_GROUPING || kw == YANG_CONTAINER || kw == YANG_CASE || kw == YANG_CHOICE || \
169 kw == YANG_ACTION || kw == YANG_RPC || kw == YANG_AUGMENT)
170
171#define HAS_META(kw) (IS_NODE_ELEM(kw) || kw == YANG_ARGUMENT || kw == YANG_IMPORT || kw == YANG_INCLUDE || kw == YANG_INPUT || kw == YANG_OUTPUT)
172
173static void
174subelems_deallocator(size_t count, struct yin_subelement *subelems)
175{
176 for(size_t i = 0; i < count; ++i) {
177 if (HAS_META(subelems[i].type)) {
178 free(subelems[i].dest);
179 }
180 }
181
182 free(subelems);
183}
184
185static LY_ERR
186subelems_allocator(struct yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
187 struct yin_subelement **result, ...)
188{
189 va_list ap;
190
191 *result = calloc(count, sizeof **result);
192 LY_CHECK_GOTO(!(*result), MEM_ERR);
193
194 va_start(ap, result);
195 for (size_t i = 0; i < count; ++i) {
196 /* TYPE */
197 (*result)[i].type = va_arg(ap, enum yang_keyword);
198 /* DEST */
199 if (IS_NODE_ELEM((*result)[i].type)) {
200 struct tree_node_meta *node_meta = NULL;
201 node_meta = calloc(1, sizeof *node_meta);
202 LY_CHECK_GOTO(!node_meta, MEM_ERR);
203 node_meta->parent = parent;
204 node_meta->siblings = va_arg(ap, void *);
205 (*result)[i].dest = node_meta;
206 } else if ((*result)[i].type == YANG_ARGUMENT) {
207 struct yin_argument_meta *arg_meta = NULL;
208 arg_meta = calloc(1, sizeof *arg_meta);
209 LY_CHECK_GOTO(!arg_meta, MEM_ERR);
210 arg_meta->argument = va_arg(ap, const char **);
211 arg_meta->flags = va_arg(ap, uint16_t *);
212 (*result)[i].dest = arg_meta;
213 } else if ((*result)[i].type == YANG_IMPORT) {
214 struct import_meta *imp_meta = NULL;
215 imp_meta = calloc(1, sizeof *imp_meta);
216 LY_CHECK_GOTO(!imp_meta, MEM_ERR);
217 imp_meta->prefix = va_arg(ap, const char *);
218 imp_meta->imports = va_arg(ap, struct lysp_import **);
219 (*result)[i].dest = imp_meta;
220 } else if ((*result)[i].type == YANG_INCLUDE) {
221 struct include_meta *inc_meta = NULL;
222 inc_meta = calloc(1, sizeof *inc_meta);
223 LY_CHECK_GOTO(!inc_meta, MEM_ERR);
224 inc_meta->name = va_arg(ap, const char *);
225 inc_meta->includes = va_arg(ap, struct lysp_include **);
226 (*result)[i].dest = inc_meta;
227 } else if ((*result)[i].type == YANG_INPUT || (*result)[i].type == YANG_OUTPUT) {
228 struct inout_meta *inout_meta = NULL;
229 inout_meta = calloc(1, sizeof *inout_meta);
230 LY_CHECK_GOTO(!inout_meta, MEM_ERR);
231 inout_meta->parent = parent;
232 inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
233 (*result)[i].dest = inout_meta;
234 } else {
235 (*result)[i].dest = va_arg(ap, void *);
236 }
237 /* FLAGS */
238 (*result)[i].flags = va_arg(ap, int);
239 }
240 va_end(ap);
241
242 return LY_SUCCESS;
243
244MEM_ERR:
245 subelems_deallocator(count, *result);
246 LOGMEM(ctx->xml_ctx.ctx);
247 return LY_EMEM;
248}
249
David Sedlák8f7a1172019-06-20 14:42:18 +0200250LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200251yin_load_attributes(struct yin_parser_ctx *ctx, const char **data, struct yin_arg_record **attrs)
David Sedláka7406952019-04-05 10:33:07 +0200252{
253 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200254 struct yin_arg_record *argument_record = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +0200255 const char *prefix, *name;
256 size_t prefix_len, name_len;
David Sedláka7406952019-04-05 10:33:07 +0200257
David Sedlák555c7202019-07-04 12:14:12 +0200258 /* load all attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +0200259 while (ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákc5b20842019-08-13 10:18:31 +0200260 ret = lyxml_get_attribute(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +0200261 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200262
David Sedlákda8ffa32019-07-08 14:17:10 +0200263 if (ctx->xml_ctx.status == LYXML_ATTR_CONTENT) {
264 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, *attrs, argument_record, ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +0200265 argument_record->name = name;
266 argument_record->name_len = name_len;
267 argument_record->prefix = prefix;
268 argument_record->prefix_len = prefix_len;
David Sedlákda8ffa32019-07-08 14:17:10 +0200269 ret = lyxml_get_string(&ctx->xml_ctx, data, &argument_record->content, &argument_record->content_len,
David Sedlák57715b12019-06-17 13:05:22 +0200270 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák00250342019-06-21 14:19:39 +0200271 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200272 }
273 }
274
David Sedlák8f7a1172019-06-20 14:42:18 +0200275cleanup:
276 if (ret != LY_SUCCESS) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200277 FREE_ARRAY(ctx, *attrs, free_arg_rec);
David Sedlákb4e44562019-07-04 15:42:12 +0200278 *attrs = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200279 }
280 return ret;
281}
282
David Sedlák4a650532019-07-10 11:55:18 +0200283LY_ERR
284yin_validate_value(struct yin_parser_ctx *ctx, enum yang_arg val_type, char *val, size_t len)
285{
286 int prefix = 0;
287 unsigned int c;
288 size_t utf8_char_len;
289 size_t already_read = 0;
290 while (already_read < len) {
291 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
292 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
293 already_read += utf8_char_len;
294 LY_CHECK_ERR_RET(already_read > len, LOGINT(ctx->xml_ctx.ctx), LY_EINT);
295
296 switch (val_type) {
297 case Y_IDENTIF_ARG:
298 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
299 break;
300 case Y_PREF_IDENTIF_ARG:
301 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
302 break;
303 case Y_STR_ARG:
304 case Y_MAYBE_STR_ARG:
305 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
306 break;
307 }
308 }
309
310 return LY_SUCCESS;
311}
312
David Sedlákb4e44562019-07-04 15:42:12 +0200313/**
314 * @brief Parse yin argument.
315 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200316 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200317 * @param[in] attrs ([Sized array](@ref sizedarrays)) of attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200318 * @param[in,out] data Data to read from.
David Sedlák4a650532019-07-10 11:55:18 +0200319 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
320 * special argument).
David Sedlákb4e44562019-07-04 15:42:12 +0200321 * @param[out] arg_val Where value of argument should be stored. Can be NULL if arg_type is specified as YIN_ARG_NONE.
David Sedlák292763b2019-07-09 11:10:53 +0200322 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200323 * @param[in] current_element Identification of current element, used for logging.
324 *
325 * @return LY_ERR values.
326 */
327static LY_ERR
David Sedlákc5b20842019-08-13 10:18:31 +0200328yin_parse_attribute(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, enum yin_argument arg_type,
David Sedlák292763b2019-07-09 11:10:53 +0200329 const char **arg_val, enum yang_arg val_type, enum yang_keyword current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200330{
David Sedlákc5b20842019-08-13 10:18:31 +0200331 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák8f7a1172019-06-20 14:42:18 +0200332 struct yin_arg_record *iter = NULL;
David Sedlák619db942019-07-03 14:47:30 +0200333 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200334
David Sedlák1bccdfa2019-06-17 15:55:27 +0200335 /* validation of attributes */
David Sedlák1f90d252019-07-10 17:09:32 +0200336 LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
David Sedlák00250342019-06-21 14:19:39 +0200337 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
338 if (!iter->prefix) {
David Sedlák060b00e2019-06-19 11:12:06 +0200339 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200340 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200341 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200342 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200343 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
David Sedlák292763b2019-07-09 11:10:53 +0200344 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200345 found = true;
David Sedlák4a650532019-07-10 11:55:18 +0200346 LY_CHECK_RET(yin_validate_value(ctx, val_type, iter->content, iter->content_len));
David Sedlák57715b12019-06-17 13:05:22 +0200347 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200348 *arg_val = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
David Sedlák619db942019-07-03 14:47:30 +0200349 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák00250342019-06-21 14:19:39 +0200350 /* string is no longer supposed to be freed when the sized array is freed */
351 iter->dynamic_content = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200352 } else {
David Sedlák99295322019-07-17 11:34:18 +0200353 if (iter->content_len == 0) {
354 *arg_val = lydict_insert(ctx->xml_ctx.ctx, "", 0);
355 } else {
356 *arg_val = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
357 LY_CHECK_RET(!(*arg_val), LY_EMEM);
358 }
David Sedlák57715b12019-06-17 13:05:22 +0200359 }
David Sedlák2b214ac2019-06-06 16:11:03 +0200360 } else {
David Sedlák1538a842019-08-08 15:38:51 +0200361 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, iter->name_len, iter->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200362 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200363 }
364 }
365 }
366
David Sedlák292763b2019-07-09 11:10:53 +0200367 /* anything else than Y_MAYBE_STR_ARG is mandatory */
368 if (val_type != Y_MAYBE_STR_ARG && !found) {
David Sedlák9c40a922019-07-08 17:04:43 +0200369 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.", yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200370 return LY_EVALID;
371 }
372
373 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200374}
375
David Sedlákd6e56892019-07-01 15:40:24 +0200376/**
David Sedlákda8ffa32019-07-08 14:17:10 +0200377 * @brief Get record with given type. Array must be sorted in ascending order by array[n].type.
David Sedlákd6e56892019-07-01 15:40:24 +0200378 *
379 * @param[in] type Type of wanted record.
380 * @param[in] array_size Size of array.
381 * @param[in] array Searched array.
382 *
383 * @return Pointer to desired record on success, NULL if element is not in the array.
384 */
David Sedlákb4e44562019-07-04 15:42:12 +0200385static struct yin_subelement *
David Sedlákb0faad82019-07-04 14:28:59 +0200386get_record(enum yang_keyword type, signed char array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200387{
David Sedlákb0faad82019-07-04 14:28:59 +0200388 signed char left = 0, right = array_size - 1, middle;
389
390 while (left <= right) {
391 middle = left + (right - left) / 2;
392
393 if (array[middle].type == type) {
394 return &array[middle];
395 }
396
397 if (array[middle].type < type) {
398 left = middle + 1;
399 } else {
400 right = middle - 1;
David Sedlákd6e56892019-07-01 15:40:24 +0200401 }
402 }
403
404 return NULL;
405}
406
David Sedlákbba38e52019-07-09 15:20:01 +0200407/**
408 * @brief Helper function to check mandatory constraint of subelement.
409 *
410 * @param[in,out] ctx Yin parser context for logging and to store current state.
411 * @param[in] subelem_info Array of information about subelements.
412 * @param[in] subelem_info_size Size of subelem_info array.
413 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
414 *
415 * @return LY_ERR values.
416 */
417static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200418yin_check_subelem_mandatory_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedlákb0faad82019-07-04 14:28:59 +0200419 signed char subelem_info_size, enum yang_keyword current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200420{
David Sedlákb0faad82019-07-04 14:28:59 +0200421 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200422 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
David Sedlák21f87cd2019-07-03 16:53:23 +0200423 if (subelem_info[i].flags & YIN_SUBELEM_MANDATORY && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200424 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200425 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200426 return LY_EVALID;
427 }
428 }
429
430 return LY_SUCCESS;
431}
432
David Sedlákbba38e52019-07-09 15:20:01 +0200433/**
434 * @brief Helper function to check "first" constraint of subelement.
435 *
436 * @param[in,out] ctx Yin parser context for logging and to store current state.
437 * @param[in] subelem_info Array of information about subelements.
438 * @param[in] subelem_info_size Size of subelem_info array.
439 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
440 * @param[in] exp_first Record in subelem_info array that is expected to be defined as first subelement.
441 *
442 * @return LY_ERR values.
443 */
444static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200445yin_check_subelem_first_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedláke1a30302019-07-10 13:49:38 +0200446 signed char subelem_info_size, enum yang_keyword current_element,
447 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200448{
David Sedlákb0faad82019-07-04 14:28:59 +0200449 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200450 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200451 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
452 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200453 return LY_EVALID;
454 }
455 }
456
457 return LY_SUCCESS;
458}
459
David Sedlákbba38e52019-07-09 15:20:01 +0200460/**
461 * @brief Helper function to check if array of information about subelements is in ascending order.
462 *
463 * @param[in] subelem_info Array of information about subelements.
464 * @param[in] subelem_info_size Size of subelem_info array.
465 *
466 * @return True iff subelem_info array is in ascending order, False otherwise.
467 */
David Sedlák5545f5d2019-07-11 11:55:16 +0200468#ifndef NDEBUG
David Sedlákbba38e52019-07-09 15:20:01 +0200469static bool
David Sedlákb0faad82019-07-04 14:28:59 +0200470is_ordered(struct yin_subelement *subelem_info, signed char subelem_info_size)
471{
David Sedlák292763b2019-07-09 11:10:53 +0200472 enum yang_keyword current = YANG_NONE; /* 0 (minimal value) */
David Sedlákb0faad82019-07-04 14:28:59 +0200473
474 for (signed char i = 0; i < subelem_info_size; ++i) {
475 if (subelem_info[i].type <= current) {
476 return false;
477 }
478 current = subelem_info[i].type;
479 }
480
481 return true;
482}
David Sedlák5545f5d2019-07-11 11:55:16 +0200483#endif
David Sedlákb0faad82019-07-04 14:28:59 +0200484
David Sedlákd6e56892019-07-01 15:40:24 +0200485/**
David Sedlákb4e44562019-07-04 15:42:12 +0200486 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
487 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200488 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200489 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200490 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákd6e56892019-07-01 15:40:24 +0200491 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákb4e44562019-07-04 15:42:12 +0200492 * @param[in] kw Type of current element.
493 * @param[out] value Where value of attribute should be stored.
494 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200495 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákda8ffa32019-07-08 14:17:10 +0200496 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200497 *
David Sedlákd6e56892019-07-01 15:40:24 +0200498 * @return LY_ERR values.
499 */
David Sedlákb4e44562019-07-04 15:42:12 +0200500static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200501yin_parse_simple_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
David Sedlákc5b20842019-08-13 10:18:31 +0200502 const char **value, enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200503{
David Sedlák1f90d252019-07-10 17:09:32 +0200504 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200505 struct yin_subelement subelems[1] = {
506 {YANG_CUSTOM, NULL, 0}
507 };
David Sedlákb4e44562019-07-04 15:42:12 +0200508
David Sedlákda8ffa32019-07-08 14:17:10 +0200509 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200510}
511
512/**
David Sedlákd3983112019-07-12 11:20:56 +0200513 * @brief Parse pattern element.
514 *
515 * @param[in,out] ctx Yin parser context for logging and to store current state.
516 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
517 * @param[in,out] data Data to read from, always moved to currently handled character.
518 * @param[in,out] patterns Restrictions to add to.
519 *
520 * @return LY_ERR values.
521 */
522static LY_ERR
523yin_parse_pattern(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
524 struct lysp_type *type)
525{
526 const char *real_value = NULL;
527 char *saved_value = NULL;
528 struct lysp_restr *restr;
529
530 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->patterns, restr, LY_EMEM);
531 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &real_value, Y_STR_ARG, YANG_PATTERN));
532 size_t len = strlen(real_value);
533
534 saved_value = malloc(len + 2);
535 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
536 memmove(saved_value + 1, real_value, len);
537 FREE_STRING(ctx->xml_ctx.ctx, real_value);
538 saved_value[0] = 0x06;
539 saved_value[len + 1] = '\0';
540 restr->arg = lydict_insert_zc(ctx->xml_ctx.ctx, saved_value);
541 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
542 type->flags |= LYS_SET_PATTERN;
543
544 struct yin_subelement subelems[6] = {
545 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
546 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
547 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
548 {YANG_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
549 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
550 {YANG_CUSTOM, NULL, 0}
551 };
552 return yin_parse_content(ctx, subelems, 6, data, YANG_PATTERN, NULL, &restr->exts);
553}
554
David Sedlákc5b20842019-08-13 10:18:31 +0200555/**
556 * @brief Parse fraction-digits element.
557 *
558 * @param[in,out] ctx Yin parser context for logging and to store current state.
559 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
560 * @param[in,out] data Data to read from, always moved to currently handled character.
561 * @param[in,out] type Type structure to store value, flags and extension instances.
562 *
563 * @return LY_ERR values.
564 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200565static LY_ERR
566yin_parse_fracdigits(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
567 struct lysp_type *type)
568{
569 const char *temp_val = NULL;
570 char *ptr;
571 unsigned long int num;
572
573 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_FRACTION_DIGITS));
574
575 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200576 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200577 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
578 return LY_EVALID;
579 }
580
581 errno = 0;
582 num = strtoul(temp_val, &ptr, 10);
583 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200584 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200585 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
586 return LY_EVALID;
587 }
588 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200589 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200590 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
591 return LY_EVALID;
592 }
David Sedlák2ab5d8e2019-07-16 11:19:41 +0200593 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200594 type->fraction_digits = num;
595 type->flags |= LYS_SET_FRDIGITS;
596 struct yin_subelement subelems[1] = {
David Sedlákd1144562019-08-06 12:36:14 +0200597 {YANG_CUSTOM, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200598 };
599 return yin_parse_content(ctx, subelems, 1, data, YANG_FRACTION_DIGITS, NULL, &type->exts);
600}
601
David Sedlák07869a52019-07-12 14:28:19 +0200602/**
David Sedlák43801c92019-08-05 15:58:54 +0200603 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200604 *
605 * @param[in,out] ctx YIN parser context for logging and to store current state.
606 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
607 * @param[in,out] data Data to read from, always moved to currently handled character.
608 * @param[in] enum_kw Identification of actual keyword, can be set to YANG_BIT or YANG_ENUM.
David Sedlákc5b20842019-08-13 10:18:31 +0200609 * @param[in,out] type Type structure to store enum value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200610 *
611 * @return LY_ERR values.
612 */
David Sedlákca36c422019-07-12 12:47:55 +0200613static LY_ERR
David Sedlák43801c92019-08-05 15:58:54 +0200614yin_parse_enum(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200615{
David Sedlák07869a52019-07-12 14:28:19 +0200616 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200617
David Sedlák43801c92019-08-05 15:58:54 +0200618 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->enums, en, LY_EMEM);
619 type->flags |= LYS_SET_ENUM;
620 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_ENUM));
621 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
622 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
623 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200624
625 struct yin_subelement subelems[6] = {
David Sedlák07869a52019-07-12 14:28:19 +0200626 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
627 {YANG_IF_FEATURE, &en->iffeatures, 0},
David Sedlák07869a52019-07-12 14:28:19 +0200628 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
629 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
David Sedlák43801c92019-08-05 15:58:54 +0200630 {YANG_VALUE, en, YIN_SUBELEM_UNIQUE},
David Sedlákca36c422019-07-12 12:47:55 +0200631 {YANG_CUSTOM, NULL, 0}
632 };
David Sedlák43801c92019-08-05 15:58:54 +0200633 return yin_parse_content(ctx, subelems, 6, data, YANG_ENUM, NULL, &en->exts);
634}
635
636/**
637 * @brief Parse bit element.
638 *
639 * @param[in,out] ctx YIN parser context for logging and to store current state.
640 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
641 * @param[in,out] data Data to read from, always moved to currently handled character.
642 * @param[in] enum_kw Identification of actual keyword, can be set to YANG_BIT or YANG_ENUM.
David Sedlákc5b20842019-08-13 10:18:31 +0200643 * @param[in,out] type Type structure to store bit value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200644 *
645 * @return LY_ERR values.
646 */
647static LY_ERR
648yin_parse_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
649 struct lysp_type *type)
650{
651 struct lysp_type_enum *en;
652
653 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->bits, en, LY_EMEM);
654 type->flags |= LYS_SET_BIT;
655 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_BIT));
656 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
657
658 struct yin_subelement subelems[6] = {
659 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
660 {YANG_IF_FEATURE, &en->iffeatures, 0},
661 {YANG_POSITION, en, YIN_SUBELEM_UNIQUE},
662 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
663 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
664 {YANG_CUSTOM, NULL, 0}
665 };
666 return yin_parse_content(ctx, subelems, 6, data, YANG_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200667}
668
David Sedlákd3983112019-07-12 11:20:56 +0200669/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200670 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
671 * more instances, such as base or if-feature.
672 *
673 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200674 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200675 * @param[in,out] data Data to read from, always moved to currently handled character.
676 * @param[in] kw Type of current element.
677 * @param[out] values Parsed values to add to.
678 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200679 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlák5f8191e2019-07-08 16:35:52 +0200680 * @param[in,out] exts Extension instance to add to.
681 *
682 * @return LY_ERR values.
683 */
684static LY_ERR
685yin_parse_simple_elements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
David Sedlákc5b20842019-08-13 10:18:31 +0200686 const char ***values, enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200687{
688 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200689 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200690 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200691 struct yin_subelement subelems[1] = {
692 {YANG_CUSTOM, &index, 0}
693 };
694
David Sedlák1f90d252019-07-10 17:09:32 +0200695 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200696
697 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
698}
699
700/**
David Sedlákcf5569a2019-07-11 13:31:34 +0200701 * @brief Parse require instance element.
702 *
703 * @param[in,out] ctx Yin parser context for logging and to store current state.
704 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
705 * @param[in,out] data Data to read from, always moved to currently handled character.
706 * @prama[out] type Type structure to store value, flag and extensions.
707 *
708 * @return LY_ERR values.
709 */
710static LY_ERR
711yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
712 const char **data, struct lysp_type *type)
713{
714 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200715 struct yin_subelement subelems[1] = {
716 {YANG_CUSTOM, NULL, 0}
717 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200718
719 type->flags |= LYS_SET_REQINST;
720 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_REQUIRE_INSTANCE));
721 if (strcmp(temp_val, "true") == 0) {
722 type->require_instance = 1;
723 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák1538a842019-08-08 15:38:51 +0200724 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "require-instance");
David Sedlákcf5569a2019-07-11 13:31:34 +0200725 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
726 return LY_EVALID;
727 }
728 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
729
730 return yin_parse_content(ctx, subelems, 1, data, YANG_REQUIRE_INSTANCE, NULL, &type->exts);
731}
732
733/**
David Sedlákce77bf52019-07-11 16:59:31 +0200734 * @brief Parse modifier element.
735 *
736 * @param[in,out] ctx Yin parser context for logging and to store current state.
737 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
738 * @param[in,out] data Data to read from, always moved to currently handled character.
739 * @param[in,out] pat Value to write to.
740 * @param[in,out] exts Extension instances to add to.
741 *
742 * @return LY_ERR values.
743 */
744static LY_ERR
745yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
746 const char **pat, struct lysp_ext_instance **exts)
747{
David Sedlákd3983112019-07-12 11:20:56 +0200748 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200749 const char *temp_val;
750 char *modified_val;
751 struct yin_subelement subelems[1] = {
752 {YANG_CUSTOM, NULL, 0}
753 };
754
755 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MODIFIER));
756 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák1538a842019-08-08 15:38:51 +0200757 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "modifier");
David Sedlákce77bf52019-07-11 16:59:31 +0200758 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
759 return LY_EVALID;
760 }
David Sedlákd3983112019-07-12 11:20:56 +0200761 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200762
763 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200764 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200765 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200766 strcpy(modified_val, *pat);
767 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200768
769 /* modify the new value */
770 modified_val[0] = 0x15;
771 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
772
773 return yin_parse_content(ctx, subelems, 1, data, YANG_MODIFIER, NULL, exts);
774}
775
776/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200777 * @brief Parse a restriction element (length, range or one instance of must).
778 *
779 * @param[in,out] ctx Yin parser context for logging and to store current state.
780 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
781 * @param[in,out] data Data to read from, always moved to currently handled character.
782 * @param[in] restr_kw Identificaton of element that is being parsed, can be set to YANG_MUST, YANG_LENGTH or YANG_RANGE.
783 * @param[in]
784 */
785static LY_ERR
786yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
787 enum yang_keyword restr_kw, struct lysp_restr *restr)
788{
789 assert(restr_kw == YANG_MUST || restr_kw == YANG_LENGTH || restr_kw == YANG_RANGE);
790 struct yin_subelement subelems[5] = {
David Sedlák968ac342019-07-11 15:17:59 +0200791 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
792 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
793 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
794 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
795 {YANG_CUSTOM, NULL, 0}
796 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200797 /* argument of must is called condition, but argument of length and range is called value */
David Sedlákc5b20842019-08-13 10:18:31 +0200798 enum yin_argument arg_type = (restr_kw == YANG_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200799 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
800
801 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
802}
803
804/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200805 * @brief Parse must element.
806 *
807 * @param[in,out] ctx YIN parser context for logging and to store current state.
808 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
809 * @param[in,out] data Data to read from, always moved to currently handled character.
810 * @param[in,out] restrs Restrictions to add to.
811 *
812 * @return LY_ERR values.
813 */
814static LY_ERR
815yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
816{
817 struct lysp_restr *restr;
818
819 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
820 return yin_parse_restriction(ctx, attrs, data, YANG_MUST, restr);
821}
822
823/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200824 * @brief Parse position or value element.
825 *
826 * @param[in,out] ctx YIN parser context for logging and to store current state.
827 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
828 * @param[in,out] data Data to read from, always moved to currently handled character.
829 * @param[in] kw Type of current element, can be set to YANG_POSITION or YANG_VALUE.
830 * @param[out] enm Enum structure to save value, flags and extensions.
831 *
832 * @return LY_ERR values.
833 */
834static LY_ERR
835yin_parse_value_pos_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
836 enum yang_keyword kw, struct lysp_type_enum *enm)
837{
838 assert(kw == YANG_POSITION || kw == YANG_VALUE);
839 const char *temp_val = NULL;
840 char *ptr;
841 long int num;
842 unsigned long int unum;
843
844 /* set value flag */
845 enm->flags |= LYS_SET_VALUE;
846
847 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200848 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
David Sedlákae5378f2019-07-17 11:37:59 +0200849 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
850 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == YANG_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200851 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +0200852 goto error;
853 }
854
855 /* convert value */
856 errno = 0;
857 if (kw == YANG_VALUE) {
858 num = strtol(temp_val, &ptr, 10);
859 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200860 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +0200861 goto error;
862 }
863 } else {
864 unum = strtoul(temp_val, &ptr, 10);
865 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200866 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +0200867 goto error;
868 }
869 }
870 /* check if whole argument value was converted */
871 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200872 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlákebcd0eb2019-07-16 17:55:12 +0200873 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200874 }
875 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +0200876 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +0200877 goto error;
878 }
879 /* save correctly ternary operator can't be used because num and unum have different signes */
880 if (kw == YANG_VALUE) {
881 enm->value = num;
882 } else {
883 enm->value = unum;
884 }
885 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
886
887 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200888 struct yin_subelement subelems[1] = {
889 {YANG_CUSTOM, NULL, 0}
890 };
David Sedlák5545f5d2019-07-11 11:55:16 +0200891 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
892
893 error:
894 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
895 return LY_EVALID;
896}
897
David Sedlák05404f62019-07-24 14:11:53 +0200898
899/**
900 * @brief Parse belongs-to element.
901 *
902 * @param[in] ctx Yin parser context for logging and to store current state.
903 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
904 * @param[in,out] data Data to read from, always moved to currently handled character.
905 * @param[out] submod Structure of submodule that is being parsed.
906 * @param[in,out] exts Extension instances to add to.
907 *
908 * @return LY_ERR values
909 */
910static LY_ERR
911yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
912 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
913{
914 struct yin_subelement subelems[2] = {
915 {YANG_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
916 {YANG_CUSTOM, NULL, 0}
917 };
918 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, YANG_BELONGS_TO));
919
920 return yin_parse_content(ctx, subelems, 2, data, YANG_BELONGS_TO, NULL, exts);
921}
922
David Sedlák5545f5d2019-07-11 11:55:16 +0200923/**
David Sedlákc1771b12019-07-10 15:55:46 +0200924 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákb4e44562019-07-04 15:42:12 +0200925 * text element as child
926 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200927 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +0200928 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200929 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákc1771b12019-07-10 15:55:46 +0200930 * @param[in] Type of element can be set to YANG_ORGANIZATION or YANG_CONTACT or YANG_DESCRIPTION or YANG_REFERENCE.
David Sedlákb4e44562019-07-04 15:42:12 +0200931 * @param[out] value Where the content of meta element should be stored.
David Sedlákbba38e52019-07-09 15:20:01 +0200932 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200933 *
934 * @return LY_ERR values.
935 */
936static LY_ERR
David Sedlákdf2a9732019-08-07 13:23:16 +0200937yin_parse_meta_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
938 enum yang_keyword elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200939{
940 assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
941
David Sedlák968ac342019-07-11 15:17:59 +0200942 struct yin_subelement subelems[2] = {
943 {YANG_CUSTOM, NULL, 0},
944 {YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
945 };
David Sedlákdf2a9732019-08-07 13:23:16 +0200946 /* check attributes */
947 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, elem_type));
David Sedlákb4e44562019-07-04 15:42:12 +0200948
David Sedlákdf2a9732019-08-07 13:23:16 +0200949 /* parse content */
David Sedlákda8ffa32019-07-08 14:17:10 +0200950 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200951}
952
953/**
David Sedlákc1771b12019-07-10 15:55:46 +0200954 * @brief Parse error-message element.
955 *
956 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +0200957 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákc1771b12019-07-10 15:55:46 +0200958 * @param[in,out] data Data to read from.
959 * @param[out] value Where the content of error-message element should be stored.
960 * @param[in,out] exts Extension instance to add to.
961 *
962 * @return LY_ERR values.
963 */
964static LY_ERR
David Sedlákdf2a9732019-08-07 13:23:16 +0200965yin_parse_err_msg_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
966 const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +0200967{
David Sedlák968ac342019-07-11 15:17:59 +0200968 struct yin_subelement subelems[2] = {
969 {YANG_CUSTOM, NULL, 0},
970 {YIN_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
971 };
David Sedlákc1771b12019-07-10 15:55:46 +0200972
David Sedlákdf2a9732019-08-07 13:23:16 +0200973 /* check attributes */
974 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, YANG_ERROR_MESSAGE));
975
David Sedlákc1771b12019-07-10 15:55:46 +0200976 return yin_parse_content(ctx, subelems, 2, data, YANG_ERROR_MESSAGE, NULL, exts);
977}
978
979/**
David Sedlák374d2b32019-07-17 15:06:55 +0200980 * @brief parse type element.
981 *
982 * @brief Parse position or value element.
983 *
984 * @param[in,out] ctx YIN parser context for logging and to store current state.
985 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
986 * @param[in,out] data Data to read from, always moved to currently handled character.
987 * @param[in,out] type Type to wrote to.
988 * @param[in,out] exts Extension instance to add to.
989 *
990 * @return LY_ERR values.
991 */
992static LY_ERR
993yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_type *type)
994{
995 struct yin_subelement subelems[11] = {
996 {YANG_BASE, type, 0},
997 {YANG_BIT, type, 0},
998 {YANG_ENUM, type, 0},
999 {YANG_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1000 {YANG_LENGTH, type, YIN_SUBELEM_UNIQUE},
1001 {YANG_PATH, type, YIN_SUBELEM_UNIQUE},
1002 {YANG_PATTERN, type, 0},
1003 {YANG_RANGE, type, YIN_SUBELEM_UNIQUE},
1004 {YANG_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1005 {YANG_TYPE, type},
1006 {YANG_CUSTOM, NULL, 0},
1007 };
1008 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, YANG_TYPE));
1009 return yin_parse_content(ctx, subelems, 11, data, YANG_TYPE, NULL, &type->exts);
1010}
1011
David Sedlák1af868e2019-07-17 17:03:14 +02001012/**
1013 * @brief Parse max-elements element.
1014 *
1015 * @param[in,out] ctx YIN parser context for logging and to store current state.
1016 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1017 * @param[in,out] data Data to read from, always moved to currently handled character.
1018 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001019 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001020 * @param[in,out] exts Extension instances to add to.
1021 *
1022 * @return LY_ERR values.
1023 */
1024static LY_ERR
1025yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
1026 uint16_t *flags, struct lysp_ext_instance **exts)
1027{
1028 const char *temp_val = NULL;
1029 char *ptr;
1030 unsigned long int num;
1031 struct yin_subelement subelems[1] = {
1032 {YANG_CUSTOM, NULL, 0},
1033 };
David Sedlák374d2b32019-07-17 15:06:55 +02001034
David Sedlák1af868e2019-07-17 17:03:14 +02001035 *flags |= LYS_SET_MAX;
1036 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MAX_ELEMENTS));
1037 if (!temp_val || temp_val[0] == '\0' || temp_val[0] == '0' || (temp_val[0] != 'u' && !isdigit(temp_val[0]))) {
David Sedlák1538a842019-08-08 15:38:51 +02001038 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001039 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1040 return LY_EVALID;
1041 }
1042
1043 if (strcmp(temp_val, "unbounded")) {
1044 errno = 0;
1045 num = strtoul(temp_val, &ptr, 10);
1046 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001047 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001048 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1049 return LY_EVALID;
1050 }
1051 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001052 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001053 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1054 return LY_EVALID;
1055 }
1056 *max = num;
1057 }
1058 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1059 return yin_parse_content(ctx, subelems, 1, data, YANG_MAX_ELEMENTS, NULL, exts);
1060}
David Sedlák374d2b32019-07-17 15:06:55 +02001061
1062/**
David Sedlák09e18c92019-07-18 11:17:11 +02001063 * @brief Parse max-elements element.
1064 *
1065 * @param[in,out] ctx YIN parser context for logging and to store current state.
1066 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1067 * @param[in,out] data Data to read from, always moved to currently handled character.
1068 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001069 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001070 * @param[in,out] exts Extension instances to add to.
1071 *
1072 * @return LY_ERR values.
1073 */
1074static LY_ERR
1075yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
1076 uint16_t *flags, struct lysp_ext_instance **exts)
1077{
1078 const char *temp_val = NULL;
1079 char *ptr;
1080 unsigned long int num;
1081 struct yin_subelement subelems[1] = {
1082 {YANG_CUSTOM, NULL, 0},
1083 };
1084
1085 *flags |= LYS_SET_MIN;
David Sedláka2dad212019-07-18 12:45:19 +02001086 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MIN_ELEMENTS));
David Sedlák09e18c92019-07-18 11:17:11 +02001087
1088 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001089 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001090 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1091 return LY_EVALID;
1092 }
1093
1094 errno = 0;
1095 num = strtoul(temp_val, &ptr, 10);
1096 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001097 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001098 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1099 return LY_EVALID;
1100 }
1101 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001102 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001103 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1104 return LY_EVALID;
1105 }
1106 *min = num;
1107 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001108 return yin_parse_content(ctx, subelems, 1, data, YANG_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001109}
1110
David Sedláka2dad212019-07-18 12:45:19 +02001111/**
1112 * @brief Parse min-elements or max-elements element.
1113 *
1114 * @param[in,out] ctx YIN parser context for logging and to store current state.
1115 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1116 * @param[in,out] data Data to read from, always moved to currently handled character.
1117 * @param[in] parent Identification of parent element.
1118 * @param[in] current Identification of current element.
1119 * @param[in] dest Where the parsed value and flags should be stored.
1120 *
1121 * @return LY_ERR values.
1122 */
David Sedlák09e18c92019-07-18 11:17:11 +02001123static LY_ERR
1124yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1125 enum yang_keyword parent, enum yang_keyword current, void *dest)
1126{
1127 assert(current == YANG_MAX_ELEMENTS || current == YANG_MIN_ELEMENTS);
David Sedlák4ffcec82019-07-25 15:10:21 +02001128 assert(parent == YANG_LEAF_LIST || parent == YANG_REFINE || parent == YANG_LIST || parent == YANG_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001129 uint32_t *lim;
1130 uint16_t *flags;
1131 struct lysp_ext_instance **exts;
1132
1133 if (parent == YANG_LEAF_LIST) {
1134 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
1135 flags = &((struct lysp_node_leaflist *)dest)->flags;
1136 exts = &((struct lysp_node_leaflist *)dest)->exts;
1137 } else if (parent == YANG_REFINE) {
1138 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
1139 flags = &((struct lysp_refine *)dest)->flags;
1140 exts = &((struct lysp_refine *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001141 } else if (parent == YANG_LIST) {
David Sedlák09e18c92019-07-18 11:17:11 +02001142 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
1143 flags = &((struct lysp_node_list *)dest)->flags;
1144 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001145 } else {
1146 lim = ((struct minmax_dev_meta *)dest)->lim;
1147 flags = ((struct minmax_dev_meta *)dest)->flags;
1148 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001149 }
1150
1151 if (current == YANG_MAX_ELEMENTS) {
1152 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1153 } else {
1154 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1155 }
1156
1157 return LY_SUCCESS;
1158}
1159
1160/**
David Sedláka2dad212019-07-18 12:45:19 +02001161 * @brief Parser ordered-by element.
1162 *
1163 * @param[in,out] ctx YIN parser context for logging and to store current state.
1164 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1165 * @param[in,out] data Data to read from, always moved to currently handled character.
1166 * @param[out] flags Flags to write to.
1167 * @param[in,out] exts Extension instance to add to.
1168 *
1169 * @return LY_ERR values.
1170 */
1171static LY_ERR
1172yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1173 uint16_t *flags, struct lysp_ext_instance **exts)
1174{
1175 const char *temp_val;
1176 struct yin_subelement subelems[1] = {
1177 {YANG_CUSTOM, NULL, 0},
1178 };
1179
1180 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_ORDERED_BY));
1181 if (strcmp(temp_val, "system") == 0) {
1182 *flags |= LYS_ORDBY_SYSTEM;
1183 } else if (strcmp(temp_val, "user") == 0) {
1184 *flags |= LYS_ORDBY_USER;
1185 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001186 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "ordered-by");
David Sedláka2dad212019-07-18 12:45:19 +02001187 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1188 return LY_EVALID;
1189 }
1190 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1191
1192 return yin_parse_content(ctx, subelems, 1, data, YANG_ORDERED_BY, NULL, exts);
1193}
1194
1195/**
David Sedlák8a83bbb2019-07-18 14:46:00 +02001196 * @brief parse any-data or any-xml element.
1197 *
1198 * @param[in,out] ctx YIN parser context for logging and to store current state.
1199 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1200 * @param[in,out] data Data to read from, always moved to currently handled character.
1201 * @param[in] any_kw Identification of current element, can be set to YANG_ANY_DATA or YANG_ANY_XML
David Sedlákad83cf92019-08-13 12:53:53 +02001202 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001203 *
1204 * @return LY_ERR values.
1205 */
1206static LY_ERR
1207yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1208 enum yang_keyword any_kw, struct tree_node_meta *node_meta)
1209{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001210 struct lysp_node_anydata *any;
1211
David Sedlák8d552d62019-08-06 15:29:05 +02001212 /* create new sibling */
1213 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, any, next);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001214 any->nodetype = (any_kw == YANG_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
1215 any->parent = node_meta->parent;
1216
David Sedlák8a83bbb2019-07-18 14:46:00 +02001217 /* parser argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001218 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &any->name, Y_IDENTIF_ARG, any_kw));
David Sedlák8a83bbb2019-07-18 14:46:00 +02001219
1220 struct yin_subelement subelems[9] = {
1221 {YANG_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1222 {YANG_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1223 {YANG_IF_FEATURE, &any->iffeatures, 0},
1224 {YANG_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1225 {YANG_MUST, &any->musts, 0},
1226 {YANG_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1227 {YANG_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1228 {YANG_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1229 {YANG_CUSTOM, NULL, 0},
1230 };
1231 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1232}
1233
1234/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001235 * @brief parse leaf element.
1236 *
1237 * @param[in,out] ctx YIN parser context for logging and to store current state.
1238 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1239 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001240 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001241 *
1242 * @return LY_ERR values.
1243 */
1244static LY_ERR
1245yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1246 struct tree_node_meta *node_meta)
1247{
David Sedlák203ca3a2019-07-18 15:26:25 +02001248 struct lysp_node_leaf *leaf;
1249
David Sedlák8d552d62019-08-06 15:29:05 +02001250 /* create structure new leaf */
1251 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, leaf, next);
David Sedlák203ca3a2019-07-18 15:26:25 +02001252 leaf->nodetype = LYS_LEAF;
1253 leaf->parent = node_meta->parent;
1254
David Sedlák203ca3a2019-07-18 15:26:25 +02001255 /* parser argument */
1256 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, YANG_LEAF));
1257
1258 /* parse content */
1259 struct yin_subelement subelems[12] = {
1260 {YANG_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1261 {YANG_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1262 {YANG_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1263 {YANG_IF_FEATURE, &leaf->iffeatures, 0},
1264 {YANG_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1265 {YANG_MUST, &leaf->musts, 0},
1266 {YANG_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1267 {YANG_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1268 {YANG_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1269 {YANG_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1270 {YANG_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1271 {YANG_CUSTOM, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001272 };
David Sedlák203ca3a2019-07-18 15:26:25 +02001273 return yin_parse_content(ctx, subelems, 12, data, YANG_LEAF, NULL, &leaf->exts);
1274}
1275
1276/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001277 * @brief Parse leaf-list element.
1278 *
1279 * @param[in,out] ctx YIN parser context for logging and to store current state.
1280 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1281 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001282 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001283 *
1284 * @return LY_ERR values.
1285 */
1286static LY_ERR
1287yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1288 struct tree_node_meta *node_meta)
1289{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001290 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001291
David Sedlák8d552d62019-08-06 15:29:05 +02001292 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, llist, next);
1293
David Sedlákc3da3ef2019-07-19 12:56:08 +02001294 llist->nodetype = LYS_LEAFLIST;
1295 llist->parent = node_meta->parent;
1296
David Sedlákc3da3ef2019-07-19 12:56:08 +02001297 /* parse argument */
1298 yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, YANG_LEAF_LIST);
1299
1300 /* parse content */
1301 struct yin_subelement subelems[14] = {
1302 {YANG_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1303 {YANG_DEFAULT, &llist->dflts, 0},
1304 {YANG_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1305 {YANG_IF_FEATURE, &llist->iffeatures, 0},
1306 {YANG_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1307 {YANG_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1308 {YANG_MUST, &llist->musts, 0},
1309 {YANG_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1310 {YANG_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1311 {YANG_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1312 {YANG_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1313 {YANG_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1314 {YANG_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1315 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001316 };
David Sedlákc3da3ef2019-07-19 12:56:08 +02001317 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, YANG_LEAF_LIST, NULL, &llist->exts));
1318
1319 /* invalid combination of subelements */
1320 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001321 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001322 return LY_EVALID;
1323 }
1324 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001325 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001326 return LY_EVALID;
1327 }
1328
1329 return LY_SUCCESS;
1330}
1331
1332/**
David Sedlák04e17b22019-07-19 15:29:48 +02001333 * @brief Parse typedef element.
1334 *
1335 * @param[in,out] ctx YIN parser context for logging and to store current state.
1336 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1337 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001338 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001339 *
1340 * @return LY_ERR values.
1341 */
1342static LY_ERR
1343yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02001344 struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001345{
1346 struct lysp_tpdf *tpdf;
David Sedlák6881b512019-08-13 12:52:00 +02001347 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->siblings;
1348 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001349
1350 /* parse argument */
1351 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, YANG_TYPEDEF));
1352
1353 /* parse content */
1354 struct yin_subelement subelems[7] = {
1355 {YANG_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1356 {YANG_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1357 {YANG_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1358 {YANG_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1359 {YANG_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1360 {YANG_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1361 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001362 };
David Sedlák04e17b22019-07-19 15:29:48 +02001363 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, YANG_TYPEDEF, NULL, &tpdf->exts));
1364
1365 /* store data for collision check */
1366 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
1367 ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0);
1368 }
1369
1370 return LY_SUCCESS;
1371}
1372
1373/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001374 * @brief Parse refine element.
1375 *
1376 * @param[in,out] ctx YIN parser context for logging and to store current state.
1377 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1378 * @param[in,out] data Data to read from, always moved to currently handled character.
1379 * @param[in,out] refines Refines to add to.
1380 *
1381 * @return LY_ERR values.
1382 */
1383static LY_ERR
1384yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1385 struct lysp_refine **refines)
1386{
1387 struct lysp_refine *rf;
1388
1389 /* allocate new refine */
1390 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1391
1392 /* parse attribute */
1393 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, YANG_REFINE));
1394 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1395
1396 /* parse content */
1397 struct yin_subelement subelems[11] = {
1398 {YANG_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1399 {YANG_DEFAULT, &rf->dflts, 0},
1400 {YANG_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1401 {YANG_IF_FEATURE, &rf->iffeatures, 0},
1402 {YANG_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1403 {YANG_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1404 {YANG_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1405 {YANG_MUST, &rf->musts, 0},
1406 {YANG_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1407 {YANG_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1408 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001409 };
David Sedlákd2d676a2019-07-22 11:28:19 +02001410 return yin_parse_content(ctx, subelems, 11, data, YANG_REFINE, NULL, &rf->exts);
1411}
1412
1413/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001414 * @brief Parse uses element.
1415 *
1416 * @param[in,out] ctx YIN parser context for logging and to store current state.
1417 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1418 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001419 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001420 *
1421 * @return LY_ERR values.
1422 */
1423static LY_ERR
1424yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1425 struct tree_node_meta *node_meta)
1426{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001427 struct lysp_node_uses *uses;
1428
David Sedlák8d552d62019-08-06 15:29:05 +02001429 /* create new uses */
1430 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, uses, next);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001431 uses->nodetype = LYS_USES;
1432 uses->parent = node_meta->parent;
1433
David Sedlák0d6de5a2019-07-22 13:25:44 +02001434 /* parse argument */
1435 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, YANG_USES));
1436
1437 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001438 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001439 struct yin_subelement subelems[8] = {
1440 {YANG_AUGMENT, &augments, 0},
1441 {YANG_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1442 {YANG_IF_FEATURE, &uses->iffeatures, 0},
1443 {YANG_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1444 {YANG_REFINE, &uses->refines, 0},
1445 {YANG_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1446 {YANG_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1447 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001448 };
David Sedlák0d6de5a2019-07-22 13:25:44 +02001449 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, YANG_USES, NULL, &uses->exts));
1450 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1451
1452 return LY_SUCCESS;
1453}
1454
1455/**
David Sedlákaa854b02019-07-22 14:17:10 +02001456 * @brief Parse revision element.
1457 *
1458 * @param[in,out] ctx YIN parser context for logging and to store current state.
1459 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1460 * @param[in,out] data Data to read from, always moved to currently handled character.
1461 * @param[in,out] revs Parsed revisions to add to.
1462 *
1463 * @return LY_ERR values.
1464 */
1465static LY_ERR
1466yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1467 struct lysp_revision **revs)
1468{
1469 struct lysp_revision *rev;
1470 const char *temp_date = NULL;
1471
1472 /* allocate new reivison */
1473 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1474
1475 /* parse argument */
1476 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, YANG_REVISION));
1477 /* check value */
1478 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1479 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1480 return LY_EVALID;
1481 }
1482 strcpy(rev->date, temp_date);
1483 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1484
1485 /* parse content */
1486 struct yin_subelement subelems[3] = {
1487 {YANG_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1488 {YANG_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1489 {YANG_CUSTOM, NULL, 0},
1490 };
1491 return yin_parse_content(ctx, subelems, 3, data, YANG_REVISION, NULL, &rev->exts);
1492}
1493
David Sedlák5e13dea2019-07-22 16:06:45 +02001494/**
1495 * @brief Parse include element.
1496 *
1497 * @param[in,out] ctx YIN parser context for logging and to store current state.
1498 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1499 * @param[in,out] data Data to read from, always moved to currently handled character.
1500 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1501 *
1502 * @return LY_ERR values.
1503 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001504static LY_ERR
1505yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1506 struct include_meta *inc_meta)
1507{
1508 struct lysp_include *inc;
1509
1510 /* allocate new include */
1511 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1512
1513 /* parse argument */
1514 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, YANG_INCLUDE));
1515
1516 /* submodules share the namespace with the module names, so there must not be
1517 * a module of the same name in the context, no need for revision matching */
1518 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xml_ctx.ctx, inc->name)) {
David Sedlák1538a842019-08-08 15:38:51 +02001519 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001520 return LY_EVALID;
1521 }
1522
1523 /* parse content */
1524 struct yin_subelement subelems[4] = {
1525 {YANG_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1526 {YANG_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1527 {YANG_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1528 {YANG_CUSTOM, NULL, 0},
1529 };
1530 return yin_parse_content(ctx, subelems, 4, data, YANG_INCLUDE, NULL, &inc->exts);
1531}
1532
David Sedlákaa854b02019-07-22 14:17:10 +02001533/**
David Sedlákdfbbb442019-08-06 16:33:21 +02001534 * @brief Parse revision date element.
1535 *
1536 * @param[in,out] ctx Yin parser context for logging and to store current state.
1537 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of revision-date element.
1538 * @param[in,out] data Data to read from, always moved to currently handled character.
1539 * @param[in,out] rev Array to store the parsed value in.
1540 * @param[in,out] exts Extension instances to add to.
1541 *
1542 * @return LY_ERR values.
1543 */
1544static LY_ERR
1545yin_parse_revision_date(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, char *rev,
1546 struct lysp_ext_instance **exts)
1547{
1548 const char *temp_rev;
1549 struct yin_subelement subelems[1] = {
1550 {YANG_CUSTOM, NULL, 0}
1551 };
1552
1553 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, YANG_REVISION_DATE));
1554 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
1555 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
1556
1557 strcpy(rev, temp_rev);
1558 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
1559
1560 return yin_parse_content(ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
1561}
1562
1563/**
1564 * @brief Parse config element.
1565 *
1566 * @param[in] ctx Yin parser context for logging and to store current state.
1567 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1568 * @param[in,out] data Data to read from, always moved to currently handled character.
1569 * @param[in,out] flags Flags to add to.
1570 * @param[in,out] exts Extension instances to add to.
1571 *
1572 * @return LY_ERR values.
1573 */
1574static LY_ERR
1575yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1576 struct lysp_ext_instance **exts)
1577{
1578 const char *temp_val = NULL;
1579 struct yin_subelement subelems[1] = {
1580 {YANG_CUSTOM, NULL, 0}
1581 };
1582
1583 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_CONFIG));
1584 if (strcmp(temp_val, "true") == 0) {
1585 *flags |= LYS_CONFIG_W;
1586 } else if (strcmp(temp_val, "false") == 0) {
1587 *flags |= LYS_CONFIG_R;
1588 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001589 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "config");
David Sedlákdfbbb442019-08-06 16:33:21 +02001590 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1591 return LY_EVALID;
1592 }
1593 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1594
1595 return yin_parse_content(ctx, subelems, 1, data, YANG_CONFIG, NULL, exts);
1596}
1597
1598/**
1599 * @brief Parse yang-version element.
1600 *
1601 * @param[in,out] ctx Yin parser context for logging and to store current state.
1602 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yang-version element.
1603 * @param[in] data Data to read from, always moved to currently handled character.
1604 * @param[out] version Storage for the parsed information.
1605 * @param[in,out] exts Extension instance to add to.
1606 *
1607 * @return LY_ERR values.
1608 */
1609static LY_ERR
1610yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
1611 struct lysp_ext_instance **exts)
1612{
1613 const char *temp_version = NULL;
1614 struct yin_subelement subelems[1] = {
1615 {YANG_CUSTOM, NULL, 0}
1616 };
1617
1618 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, YANG_YANG_VERSION));
1619 if (strcmp(temp_version, "1.0") == 0) {
1620 *version = LYS_VERSION_1_0;
1621 } else if (strcmp(temp_version, "1.1") == 0) {
1622 *version = LYS_VERSION_1_1;
1623 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001624 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_version, "value", "yang-version");
David Sedlákdfbbb442019-08-06 16:33:21 +02001625 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1626 return LY_EVALID;
1627 }
1628 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1629 ctx->mod_version = *version;
1630
1631 return yin_parse_content(ctx, subelems, 1, data, YANG_YANG_VERSION, NULL, exts);
1632}
1633
1634/**
1635 * @brief Parse import element.
1636 *
1637 * @param[in,out] ctx Yin parser context for logging and to store current state.
1638 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1639 * @param[in,out] data Data to read from, always moved to currently handled character.
1640 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1641 *
1642 * @return LY_ERR values.
1643 */
1644static LY_ERR
1645yin_parse_import(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct import_meta *imp_meta)
1646{
1647 struct lysp_import *imp;
1648 /* allocate new element in sized array for import */
1649 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
1650
1651 struct yin_subelement subelems[5] = {
1652 {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1653 {YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1654 {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1655 {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1656 {YANG_CUSTOM, NULL, 0}
1657 };
1658
1659 /* parse import attributes */
1660 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, YANG_IMPORT));
1661 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
1662 /* check prefix validity */
1663 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1664
1665 return LY_SUCCESS;
1666}
1667
1668/**
1669 * @brief Parse mandatory element.
1670 *
1671 * @param[in,out] ctx Yin parser context for logging and to store current state.
1672 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1673 * @param[in,out] data Data to read from, always moved to currently handled character.
1674 * @param[in,out] flags Flags to add to.
1675 * @param[in,out] exts Extension instances to add to.
1676 *
1677 * @return LY_ERR values.
1678 */
1679static LY_ERR
1680yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1681 struct lysp_ext_instance **exts)
1682{
1683 const char *temp_val = NULL;
1684 struct yin_subelement subelems[1] = {
1685 {YANG_CUSTOM, NULL, 0}
1686 };
1687
1688 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MANDATORY));
1689 if (strcmp(temp_val, "true") == 0) {
1690 *flags |= LYS_MAND_TRUE;
1691 } else if (strcmp(temp_val, "false") == 0) {
1692 *flags |= LYS_MAND_FALSE;
1693 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001694 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "mandatory");
David Sedlákdfbbb442019-08-06 16:33:21 +02001695 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1696 return LY_EVALID;
1697 }
1698 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1699
1700 return yin_parse_content(ctx, subelems, 1, data, YANG_MANDATORY, NULL, exts);
1701}
1702
1703/**
1704 * @brief Parse status element.
1705 *
1706 * @param[in,out] ctx Yin parser context for logging and to store current state.
1707 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1708 * @param[in,out] data Data to read from, always moved to currently handled character.
1709 * @param[in,out] flags Flags to add to.
1710 * @param[in,out] exts Extension instances to add to.
1711 *
1712 * @return LY_ERR values.
1713 */
1714static LY_ERR
1715yin_parse_status(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1716 struct lysp_ext_instance **exts)
1717{
1718 const char *value = NULL;
1719 struct yin_subelement subelems[1] = {
1720 {YANG_CUSTOM, NULL, 0}
1721 };
1722
1723 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &value, Y_STR_ARG, YANG_STATUS));
1724 if (strcmp(value, "current") == 0) {
1725 *flags |= LYS_STATUS_CURR;
1726 } else if (strcmp(value, "deprecated") == 0) {
1727 *flags |= LYS_STATUS_DEPRC;
1728 } else if (strcmp(value, "obsolete") == 0) {
1729 *flags |= LYS_STATUS_OBSLT;
1730 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001731 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, value, "value", "status");
David Sedlákdfbbb442019-08-06 16:33:21 +02001732 FREE_STRING(ctx->xml_ctx.ctx, value);
1733 return LY_EVALID;
1734 }
1735 FREE_STRING(ctx->xml_ctx.ctx, value);
1736
1737 return yin_parse_content(ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
1738}
1739
1740/**
1741 * @brief Parse when element.
1742 *
1743 * @param[in,out] ctx Yin parser context for logging and to store current state.
1744 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of when element.
1745 * @param[in,out] data Data to read from, always moved to currently handled character.
1746 * @param[out] when_p When pointer to parse to.
1747 */
1748static LY_ERR
1749yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
1750{
1751 struct lysp_when *when;
1752 when = calloc(1, sizeof *when);
1753 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1754 yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, YANG_WHEN);
1755 *when_p = when;
1756 struct yin_subelement subelems[3] = {
1757 {YANG_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1758 {YANG_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1759 {YANG_CUSTOM, NULL, 0}
1760 };
1761
1762 return yin_parse_content(ctx, subelems, 3, data, YANG_WHEN, NULL, &when->exts);
1763}
1764
1765/**
1766 * @brief Parse yin-elemenet element.
1767 *
1768 * @param[in,out] ctx Yin parser context for logging and to store current state.
1769 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yin-element element.
1770 * @param[in,out] data Data to read from, always moved to currently handled position.
1771 * @param[in,out] flags Flags to add to.
1772 * @prama[in,out] exts Extension instance to add to.
1773 *
1774 * @return LY_ERR values.
1775 */
1776static LY_ERR
1777yin_parse_yin_element_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1778 uint16_t *flags, struct lysp_ext_instance **exts)
1779{
1780 const char *temp_val = NULL;
1781 struct yin_subelement subelems[1] = {
1782 {YANG_CUSTOM, NULL, 0}
1783 };
1784
1785 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_YIN_ELEMENT));
1786 if (strcmp(temp_val, "true") == 0) {
1787 *flags |= LYS_YINELEM_TRUE;
1788 } else if (strcmp(temp_val, "false") == 0) {
1789 *flags |= LYS_YINELEM_FALSE;
1790 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001791 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "yin-element");
David Sedlákdfbbb442019-08-06 16:33:21 +02001792 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1793 return LY_EVALID;
1794 }
1795 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1796
1797 return yin_parse_content(ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
1798}
1799
1800/**
1801 * @brief Parse argument element.
1802 *
1803 * @param[in,out] xml_ctx Xml context.
1804 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of argument element.
1805 * @param[in,out] data Data to read from, always moved to currently handled character.
1806 * @param[in,out] arg_meta Meta information about destionation af prased data.
1807 * @param[in,out] exts Extension instance to add to.
1808 *
1809 * @return LY_ERR values.
1810 */
1811static LY_ERR
1812yin_parse_argument_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1813 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
1814{
1815 struct yin_subelement subelems[2] = {
1816 {YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1817 {YANG_CUSTOM, NULL, 0}
1818 };
1819
1820 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, YANG_ARGUMENT));
1821
1822 return yin_parse_content(ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
1823}
1824
1825/**
1826 * @brief Parse the extension statement.
1827 *
1828 * @param[in,out] ctx Yin parser context for logging and to store current state.
1829 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension element.
1830 * @param[in,out] data Data to read from.
1831 * @param[in,out] extensions Extensions to add to.
1832 *
1833 * @return LY_ERR values.
1834 */
1835static LY_ERR
1836yin_parse_extension(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_ext **extensions)
1837{
1838 struct lysp_ext *ex;
1839 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
1840 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ex->name, Y_IDENTIF_ARG, YANG_EXTENSION));
1841
1842 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1843 struct yin_subelement subelems[5] = {
1844 {YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1845 {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1846 {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1847 {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1848 {YANG_CUSTOM, NULL, 0}
1849 };
1850
1851 return yin_parse_content(ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
1852}
1853
1854/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001855 * @brief Parse feature element.
1856 *
1857 * @param[in,out] ctx YIN parser context for logging and to store current state.
1858 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1859 * @param[in,out] data Data to read from, always moved to currently handled character.
1860 * @param[in,out] features Features to add to.
1861 *
1862 * @return LY_ERR values.
1863 */
1864static LY_ERR
1865yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1866 struct lysp_feature **features)
1867{
1868 struct lysp_feature *feat;
1869
1870 /* allocate new feature */
1871 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
1872
1873 /* parse argument */
1874 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, YANG_FEATURE));
1875
1876 /* parse content */
1877 struct yin_subelement subelems[5] = {
1878 {YANG_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1879 {YANG_IF_FEATURE, &feat->iffeatures, 0},
1880 {YANG_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1881 {YANG_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1882 {YANG_CUSTOM, NULL, 0},
1883 };
1884 return yin_parse_content(ctx, subelems, 5, data, YANG_FEATURE, NULL, &feat->exts);
1885}
1886
1887/**
David Sedlák28794f22019-07-22 16:45:00 +02001888 * @brief Parse identity element.
1889 *
1890 * @param[in,out] ctx YIN parser context for logging and to store current state.
1891 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1892 * @param[in,out] data Data to read from, always moved to currently handled character.
1893 * @param[in,out] identities Identities to add to.
1894 *
1895 * @return LY_ERR values.
1896 */
1897static LY_ERR
1898yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1899 struct lysp_ident **identities)
1900{
1901 struct lysp_ident *ident;
1902
1903 /* allocate new identity */
1904 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
1905
1906 /* parse argument */
1907 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, YANG_IDENTITY));
1908
1909 /* parse content */
1910 struct yin_subelement subelems[6] = {
1911 {YANG_BASE, &ident->bases, 0},
1912 {YANG_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
1913 {YANG_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
1914 {YANG_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
1915 {YANG_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
1916 {YANG_CUSTOM, NULL, 0},
1917 };
1918 return yin_parse_content(ctx, subelems, 6, data, YANG_IDENTITY, NULL, &ident->exts);
1919}
1920
1921/**
David Sedlákaf536aa2019-07-23 13:42:23 +02001922 * @brief Parse list element.
1923 *
1924 * @param[in,out] ctx YIN parser context for logging and to store current state.
1925 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1926 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001927 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02001928 *
1929 * @return LY_ERR values.
1930 */
1931static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02001932yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1933 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02001934{
David Sedlákaf536aa2019-07-23 13:42:23 +02001935 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02001936 LY_ERR ret = LY_SUCCESS;
1937 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02001938
David Sedlák8d552d62019-08-06 15:29:05 +02001939 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, list, next);
David Sedlákaf536aa2019-07-23 13:42:23 +02001940 list->nodetype = LYS_LIST;
1941 list->parent = node_meta->parent;
1942
David Sedlákaf536aa2019-07-23 13:42:23 +02001943 /* parse argument */
1944 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, YANG_LIST));
1945
1946 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02001947 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
1948 YANG_ACTION, &list->actions, 0,
1949 YANG_ANYDATA, &list->child, 0,
1950 YANG_ANYXML, &list->child, 0,
1951 YANG_CHOICE, &list->child, 0,
1952 YANG_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
1953 YANG_CONTAINER, &list->child, 0,
1954 YANG_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
1955 YANG_GROUPING, &list->groupings, 0,
1956 YANG_IF_FEATURE, &list->iffeatures, 0,
1957 YANG_KEY, &list->key, YIN_SUBELEM_UNIQUE,
1958 YANG_LEAF, &list->child, 0,
1959 YANG_LEAF_LIST, &list->child, 0,
1960 YANG_LIST, &list->child, 0,
1961 YANG_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
1962 YANG_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
1963 YANG_MUST, &list->musts, 0,
1964 YANG_NOTIFICATION, &list->notifs, 0,
1965 YANG_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
1966 YANG_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
1967 YANG_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
1968 YANG_TYPEDEF, &list->typedefs, 0,
1969 YANG_UNIQUE, &list->uniques, 0,
1970 YANG_USES, &list->child, 0,
1971 YANG_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
1972 YANG_CUSTOM, NULL, 0
1973 ));
1974 ret = yin_parse_content(ctx, subelems, 25, data, YANG_LIST, NULL, &list->exts);
1975 subelems_deallocator(25, subelems);
1976 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02001977
1978 /* finalize parent pointers to the reallocated items */
1979 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
1980
1981 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001982 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02001983 return LY_EVALID;
1984 }
1985
1986 return LY_SUCCESS;
1987}
1988
1989/**
David Sedlák031b9e72019-07-23 15:19:37 +02001990 * @brief Parse notification element.
1991 *
1992 * @param[in,out] ctx YIN parser context for logging and to store current state.
1993 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1994 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001995 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02001996 *
1997 * @return LY_ERR values.
1998 */
1999static LY_ERR
2000yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002001 struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002002{
2003 struct lysp_notif *notif;
David Sedlák6881b512019-08-13 12:52:00 +02002004 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->siblings;
David Sedlák81497a32019-08-13 16:56:26 +02002005 LY_ERR ret = LY_SUCCESS;
2006 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002007
2008 /* allocate new notification */
David Sedlák6881b512019-08-13 12:52:00 +02002009 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002010 notif->nodetype = LYS_NOTIF;
2011 notif->parent = notif_meta->parent;
2012
2013 /* parse argument */
2014 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, YANG_NOTIFICATION));
2015
2016 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002017 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
2018 YANG_ANYDATA, &notif->data, 0,
2019 YANG_ANYXML, &notif->data, 0,
2020 YANG_CHOICE, &notif->data, 0,
2021 YANG_CONTAINER, &notif->data, 0,
2022 YANG_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2023 YANG_GROUPING, &notif->groupings, 0,
2024 YANG_IF_FEATURE, &notif->iffeatures, 0,
2025 YANG_LEAF, &notif->data, 0,
2026 YANG_LEAF_LIST, &notif->data, 0,
2027 YANG_LIST, &notif->data, 0,
2028 YANG_MUST, &notif->musts, YIN_SUBELEM_VER2,
2029 YANG_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2030 YANG_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2031 YANG_TYPEDEF, &notif->typedefs, 0,
2032 YANG_USES, &notif->data, 0,
2033 YANG_CUSTOM, NULL, 0
2034 ));
2035
2036 ret = yin_parse_content(ctx, subelems, 16, data, YANG_NOTIFICATION, NULL, &notif->exts);
2037 subelems_deallocator(16, subelems);
2038 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002039
2040 /* finalize parent pointers to the reallocated items */
2041 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2042
2043 return LY_SUCCESS;
2044}
2045
2046/**
David Sedláke3ce9ef2019-07-23 16:34:30 +02002047 * @brief Parse notification element.
2048 *
2049 * @param[in,out] ctx YIN parser context for logging and to store current state.
2050 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2051 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02002052 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002053 *
2054 * @return LY_ERR values.
2055 */
2056static LY_ERR
2057yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002058 struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002059{
2060 struct lysp_grp *grp;
David Sedlák6881b512019-08-13 12:52:00 +02002061 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->siblings;
David Sedlák81497a32019-08-13 16:56:26 +02002062 LY_ERR ret = LY_SUCCESS;
2063 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002064
2065 /* create new grouping */
David Sedlák6881b512019-08-13 12:52:00 +02002066 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002067 grp->nodetype = LYS_GROUPING;
2068 grp->parent = gr_meta->parent;
2069
2070 /* parse argument */
2071 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, YANG_GROUPING));
2072
2073 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002074 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
2075 YANG_ACTION, &grp->actions, 0,
2076 YANG_ANYDATA, &grp->data, 0,
2077 YANG_ANYXML, &grp->data, 0,
2078 YANG_CHOICE, &grp->data, 0,
2079 YANG_CONTAINER, &grp->data, 0,
2080 YANG_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2081 YANG_GROUPING, &grp->groupings, 0,
2082 YANG_LEAF, &grp->data, 0,
2083 YANG_LEAF_LIST, &grp->data, 0,
2084 YANG_LIST, &grp->data, 0,
2085 YANG_NOTIFICATION, &grp->notifs, 0,
2086 YANG_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2087 YANG_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2088 YANG_TYPEDEF, &grp->typedefs, 0,
2089 YANG_USES, &grp->data, 0,
2090 YANG_CUSTOM, NULL, 0
2091 ));
2092 ret = yin_parse_content(ctx, subelems, 16, data, YANG_GROUPING, NULL, &grp->exts);
2093 subelems_deallocator(16, subelems);
2094 LY_CHECK_RET(ret);
2095
David Sedláke3ce9ef2019-07-23 16:34:30 +02002096 /* finalize parent pointers to the reallocated items */
2097 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2098
2099 return LY_SUCCESS;
2100}
2101
2102/**
David Sedlákf111bcb2019-07-23 17:15:51 +02002103 * @brief Parse list element.
2104 *
2105 * @param[in,out] ctx YIN parser context for logging and to store current state.
2106 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2107 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002108 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002109 *
2110 * @return LY_ERR values.
2111 */
2112static LY_ERR
2113yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2114 struct tree_node_meta *node_meta)
2115{
David Sedlákf111bcb2019-07-23 17:15:51 +02002116 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002117 LY_ERR ret = LY_SUCCESS;
2118 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002119
2120 /* create new container */
David Sedlák8d552d62019-08-06 15:29:05 +02002121 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, cont, next);
David Sedlákf111bcb2019-07-23 17:15:51 +02002122 cont->nodetype = LYS_CONTAINER;
2123 cont->parent = node_meta->parent;
2124
David Sedlákf111bcb2019-07-23 17:15:51 +02002125 /* parse aegument */
2126 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, YANG_CONTAINER));
2127
2128 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002129 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
2130 YANG_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2131 YANG_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2132 YANG_ANYXML, &cont->child, 0,
2133 YANG_CHOICE, &cont->child, 0,
2134 YANG_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2135 YANG_CONTAINER, &cont->child, 0,
2136 YANG_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2137 YANG_GROUPING, &cont->groupings, 0,
2138 YANG_IF_FEATURE, &cont->iffeatures, 0,
2139 YANG_LEAF, &cont->child, 0,
2140 YANG_LEAF_LIST, &cont->child, 0,
2141 YANG_LIST, &cont->child, 0,
2142 YANG_MUST, &cont->musts, 0,
2143 YANG_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2144 YANG_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2145 YANG_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2146 YANG_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2147 YANG_TYPEDEF, &cont->typedefs, 0,
2148 YANG_USES, &cont->child, 0,
2149 YANG_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2150 YANG_CUSTOM, NULL, 0
2151 ));
2152 ret = yin_parse_content(ctx, subelems, 21, data, YANG_CONTAINER, NULL, &cont->exts);
2153 subelems_deallocator(21, subelems);
2154 LY_CHECK_RET(ret);
2155
David Sedlákf111bcb2019-07-23 17:15:51 +02002156 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2157
2158 return LY_SUCCESS;
2159}
2160
2161/**
David Sedlák5379d392019-07-24 10:42:03 +02002162 * @brief Parse case element.
2163 *
2164 * @param[in,out] ctx YIN parser context for logging and to store current state.
2165 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2166 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002167 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002168 *
2169 * @return LY_ERR values.
2170 */
2171static LY_ERR
2172yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2173 struct tree_node_meta *node_meta)
2174{
David Sedlák5379d392019-07-24 10:42:03 +02002175 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002176 LY_ERR ret = LY_SUCCESS;
2177 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002178
2179 /* create new case */
David Sedlák8d552d62019-08-06 15:29:05 +02002180 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, cas, next);
David Sedlák5379d392019-07-24 10:42:03 +02002181 cas->nodetype = LYS_CASE;
2182 cas->parent = node_meta->parent;
2183
David Sedlák5379d392019-07-24 10:42:03 +02002184 /* parse argument */
2185 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, YANG_CASE));
2186
2187 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002188 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
2189 YANG_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2190 YANG_ANYXML, &cas->child, 0,
2191 YANG_CHOICE, &cas->child, 0,
2192 YANG_CONTAINER, &cas->child, 0,
2193 YANG_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2194 YANG_IF_FEATURE, &cas->iffeatures, 0,
2195 YANG_LEAF, &cas->child, 0,
2196 YANG_LEAF_LIST, &cas->child, 0,
2197 YANG_LIST, &cas->child, 0,
2198 YANG_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2199 YANG_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2200 YANG_USES, &cas->child, 0,
2201 YANG_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2202 YANG_CUSTOM, NULL, 0
2203 ));
2204 ret = yin_parse_content(ctx, subelems, 14, data, YANG_CASE, NULL, &cas->exts);
2205 subelems_deallocator(14, subelems);
2206
2207 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002208}
2209
2210/**
David Sedlák05404f62019-07-24 14:11:53 +02002211 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002212 *
2213 * @param[in,out] ctx YIN parser context for logging and to store current state.
2214 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2215 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002216 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002217 *
2218 * @return LY_ERR values.
2219 */
2220LY_ERR
2221yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2222 struct tree_node_meta *node_meta)
2223{
David Sedlák81497a32019-08-13 16:56:26 +02002224 LY_ERR ret = LY_SUCCESS;
2225 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002226 struct lysp_node_choice *choice;
2227
2228 /* create new choice */
David Sedlák8d552d62019-08-06 15:29:05 +02002229 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, choice, next);
2230
David Sedlákb7abcfa2019-07-24 12:33:35 +02002231 choice->nodetype = LYS_CHOICE;
2232 choice->parent = node_meta->parent;
2233
David Sedlákb7abcfa2019-07-24 12:33:35 +02002234 /* parse argument */
2235 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, YANG_CHOICE));
2236
2237 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002238 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
2239 YANG_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2240 YANG_ANYXML, &choice->child, 0,
2241 YANG_CASE, &choice->child, 0,
2242 YANG_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2243 YANG_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2244 YANG_CONTAINER, &choice->child, 0,
2245 YANG_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2246 YANG_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2247 YANG_IF_FEATURE, &choice->iffeatures, 0,
2248 YANG_LEAF, &choice->child, 0,
2249 YANG_LEAF_LIST, &choice->child, 0,
2250 YANG_LIST, &choice->child, 0,
2251 YANG_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2252 YANG_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2253 YANG_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2254 YANG_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2255 YANG_CUSTOM, NULL, 0
2256 ));
2257 ret = yin_parse_content(ctx, subelems, 17, data, YANG_CHOICE, NULL, &choice->exts);
2258 subelems_deallocator(17, subelems);
2259 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002260}
2261
2262/**
David Sedlák05404f62019-07-24 14:11:53 +02002263 * @brief Parse input or output element.
2264 *
2265 * @param[in,out] ctx YIN parser context for logging and to store current state.
2266 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2267 * @param[in,out] data Data to read from, always moved to currently handled character.
2268 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2269 *
2270 * @return LY_ERR values.
2271 */
2272static LY_ERR
2273yin_parse_inout(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword inout_kw,
2274 struct inout_meta *inout_meta)
2275{
David Sedlák81497a32019-08-13 16:56:26 +02002276 LY_ERR ret = LY_SUCCESS;
2277 struct yin_subelement *subelems = NULL;
2278
David Sedlák05404f62019-07-24 14:11:53 +02002279 /* initiate structure */
2280 inout_meta->inout_p->nodetype = (inout_kw == YANG_INPUT) ? LYS_INPUT : LYS_OUTPUT;
2281 inout_meta->inout_p->parent = inout_meta->parent;
2282
2283 /* check attributes */
2284 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
2285
2286 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002287 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
2288 YANG_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2289 YANG_ANYXML, &inout_meta->inout_p->data, 0,
2290 YANG_CHOICE, &inout_meta->inout_p->data, 0,
2291 YANG_CONTAINER, &inout_meta->inout_p->data, 0,
2292 YANG_GROUPING, &inout_meta->inout_p->groupings, 0,
2293 YANG_LEAF, &inout_meta->inout_p->data, 0,
2294 YANG_LEAF_LIST, &inout_meta->inout_p->data, 0,
2295 YANG_LIST, &inout_meta->inout_p->data, 0,
2296 YANG_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2297 YANG_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2298 YANG_USES, &inout_meta->inout_p->data, 0,
2299 YANG_CUSTOM, NULL, 0
2300 ));
2301 ret = yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts);
2302 subelems_deallocator(12, subelems);
2303 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002304
2305 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002306 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_meta->inout_p->groupings, NULL, NULL, NULL));
David Sedlák05404f62019-07-24 14:11:53 +02002307
2308 return LY_SUCCESS;
2309}
2310
David Sedlák992fb7c2019-07-24 16:51:01 +02002311/**
2312 * @brief Parse action element.
2313 *
2314 * @param[in,out] ctx YIN parser context for logging and to store current state.
2315 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2316 * @param[in,out] data Data to read from, always moved to currently handled character.
2317 * @param[in] act_meta Meta information about parent node and actions to add to.
2318 *
2319 * @return LY_ERR values.
2320 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002321static LY_ERR
2322yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002323 struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002324{
David Sedlák81497a32019-08-13 16:56:26 +02002325 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->siblings;
2326 LY_ERR ret = LY_SUCCESS;
2327 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002328
2329 /* create new action */
David Sedlák6881b512019-08-13 12:52:00 +02002330 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *acts, act, LY_EMEM);
David Sedlák85d0eca2019-07-24 15:15:21 +02002331 act->nodetype = LYS_ACTION;
2332 act->parent = act_meta->parent;
2333
2334 /* parse argument */
2335 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, YANG_ACTION));
2336
2337 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002338 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
2339 YANG_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2340 YANG_GROUPING, &act->groupings, 0,
2341 YANG_IF_FEATURE, &act->iffeatures, 0,
2342 YANG_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2343 YANG_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2344 YANG_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2345 YANG_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2346 YANG_TYPEDEF, &act->typedefs, 0,
2347 YANG_CUSTOM, NULL, 0
2348 ));
2349 ret = (yin_parse_content(ctx, subelems, 9, data, YANG_ACTION, NULL, &act->exts));
2350 subelems_deallocator(9, subelems);
2351 LY_CHECK_RET(ret);
2352
David Sedlák85d0eca2019-07-24 15:15:21 +02002353 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2354
2355 return LY_SUCCESS;
2356}
2357
David Sedlák05404f62019-07-24 14:11:53 +02002358/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002359 * @brief Parse augment element.
2360 *
2361 * @param[in,out] ctx YIN parser context for logging and to store current state.
2362 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2363 * @param[in,out] data Data to read from, always moved to currently handled character.
2364 * @param[in] aug_meta Meta information about parent node and augments to add to.
2365 *
2366 * @return LY_ERR values.
2367 */
2368static LY_ERR
2369yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002370 struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002371{
2372 struct lysp_augment *aug;
David Sedlák6881b512019-08-13 12:52:00 +02002373 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->siblings;
David Sedlák81497a32019-08-13 16:56:26 +02002374 LY_ERR ret = LY_SUCCESS;
2375 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002376
2377 /* create new augment */
David Sedlák6881b512019-08-13 12:52:00 +02002378 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002379 aug->nodetype = LYS_AUGMENT;
2380 aug->parent = aug_meta->parent;
2381
2382 /* parse argument */
2383 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, YANG_AUGMENT));
2384 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2385
2386 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002387 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
2388 YANG_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2389 YANG_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2390 YANG_ANYXML, &aug->child, 0,
2391 YANG_CASE, &aug->child, 0,
2392 YANG_CHOICE, &aug->child, 0,
2393 YANG_CONTAINER, &aug->child, 0,
2394 YANG_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2395 YANG_IF_FEATURE, &aug->iffeatures, 0,
2396 YANG_LEAF, &aug->child, 0,
2397 YANG_LEAF_LIST, &aug->child, 0,
2398 YANG_LIST, &aug->child, 0,
2399 YANG_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2400 YANG_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2401 YANG_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2402 YANG_USES, &aug->child, 0,
2403 YANG_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2404 YANG_CUSTOM, NULL, 0
2405 ));
2406 ret = yin_parse_content(ctx, subelems, 17, data, YANG_AUGMENT, NULL, &aug->exts);
2407 subelems_deallocator(17, subelems);
2408 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002409
2410 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2411
2412 return LY_SUCCESS;
2413}
2414
David Sedlák8b754462019-07-25 16:22:13 +02002415/**
2416 * @brief Parse deviate element.
2417 *
2418 * @param[in,out] ctx YIN parser context for logging and to store current state.
2419 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2420 * @param[in,out] data Data to read from, always moved to currently handled character.
2421 * @param[in] deviates Deviates to add to.
2422 *
2423 * @return LY_ERR values.
2424 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002425static LY_ERR
2426yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2427 struct lysp_deviate **deviates)
2428{
2429 LY_ERR ret = LY_SUCCESS;
2430 uint8_t dev_mod;
2431 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002432 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002433 struct lysp_deviate_add *d_add = NULL;
2434 struct lysp_deviate_rpl *d_rpl = NULL;
2435 struct lysp_deviate_del *d_del = NULL;
2436
2437 /* parse argument */
2438 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_DEVIATE));
2439
2440 if (strcmp(temp_val, "not-supported") == 0) {
2441 dev_mod = LYS_DEV_NOT_SUPPORTED;
2442 } else if (strcmp(temp_val, "add") == 0) {
2443 dev_mod = LYS_DEV_ADD;
2444 } else if (strcmp(temp_val, "replace") == 0) {
2445 dev_mod = LYS_DEV_REPLACE;
2446 } else if (strcmp(temp_val, "delete") == 0) {
2447 dev_mod = LYS_DEV_DELETE;
2448 } else {
David Sedlák1538a842019-08-08 15:38:51 +02002449 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "deviate");
David Sedlák4ffcec82019-07-25 15:10:21 +02002450 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2451 return LY_EVALID;
2452 }
2453 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2454
2455 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2456 d = calloc(1, sizeof *d);
2457 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2458 struct yin_subelement subelems[1] = {
2459 {YANG_CUSTOM, NULL, 0}
2460 };
2461 ret = yin_parse_content(ctx, subelems, 1, data, YANG_DEVIATE, NULL, &d->exts);
2462
2463 } else if (dev_mod == LYS_DEV_ADD) {
2464 d_add = calloc(1, sizeof *d_add);
2465 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2466 d = (struct lysp_deviate *)d_add;
2467 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2468 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2469 struct yin_subelement subelems[9] = {
2470 {YANG_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2471 {YANG_DEFAULT, &d_add->dflts, 0},
2472 {YANG_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2473 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2474 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2475 {YANG_MUST, &d_add->musts, 0},
2476 {YANG_UNIQUE, &d_add->uniques, 0},
2477 {YANG_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2478 {YANG_CUSTOM, NULL, 0},
2479 };
2480 ret = yin_parse_content(ctx, subelems, 9, data, YANG_DEVIATE, NULL, &d_add->exts);
2481
2482 } else if (dev_mod == LYS_DEV_REPLACE) {
2483 d_rpl = calloc(1, sizeof *d_rpl);
2484 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2485 d = (struct lysp_deviate *)d_rpl;
2486 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2487 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2488 struct yin_subelement subelems[8] = {
2489 {YANG_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2490 {YANG_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2491 {YANG_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2492 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2493 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2494 {YANG_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2495 {YANG_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2496 {YANG_CUSTOM, NULL, 0},
2497 };
2498 ret = yin_parse_content(ctx, subelems, 8, data, YANG_DEVIATE, NULL, &d_rpl->exts);
2499
2500 } else {
2501 d_del = calloc(1, sizeof *d_del);
2502 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2503 d = (struct lysp_deviate *)d_del;
2504 struct yin_subelement subelems[5] = {
2505 {YANG_DEFAULT, &d_del->dflts, 0},
2506 {YANG_MUST, &d_del->musts, 0},
2507 {YANG_UNIQUE, &d_del->uniques, 0},
2508 {YANG_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2509 {YANG_CUSTOM, NULL, 0},
2510 };
2511 ret = yin_parse_content(ctx, subelems, 5, data, YANG_DEVIATE, NULL, &d_del->exts);
2512 }
2513 LY_CHECK_GOTO(ret, cleanup);
2514
2515 d->mod = dev_mod;
2516 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002517 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002518
2519 return ret;
2520
2521cleanup:
2522 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002523 return ret;
2524}
2525
David Sedlák992fb7c2019-07-24 16:51:01 +02002526/**
David Sedlák8b754462019-07-25 16:22:13 +02002527 * @brief Parse deviation element.
2528 *
2529 * @param[in,out] ctx YIN parser context for logging and to store current state.
2530 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2531 * @param[in,out] data Data to read from, always moved to currently handled character.
2532 * @param[in] deviations Deviations to add to.
2533 *
2534 * @return LY_ERR values.
2535 */
2536static LY_ERR
2537yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2538 struct lysp_deviation **deviations)
2539{
2540 struct lysp_deviation *dev;
2541
2542 /* create new deviation */
2543 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2544
2545 /* parse argument */
David Sedlák1538a842019-08-08 15:38:51 +02002546 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, YANG_DEVIATION));
David Sedlák8b754462019-07-25 16:22:13 +02002547 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2548 struct yin_subelement subelems[4] = {
2549 {YANG_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2550 {YANG_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2551 {YANG_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2552 {YANG_CUSTOM, NULL, 0},
2553 };
David Sedlák1538a842019-08-08 15:38:51 +02002554 return yin_parse_content(ctx, subelems, 4, data, YANG_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002555}
2556
2557/**
David Sedlákb4e44562019-07-04 15:42:12 +02002558 * @brief Map keyword type to substatement info.
2559 *
2560 * @param[in] kw Keyword type.
2561 *
2562 * @return correct LYEXT_SUBSTMT information.
2563 */
2564static LYEXT_SUBSTMT
2565kw2lyext_substmt(enum yang_keyword kw)
2566{
2567 switch (kw) {
2568 case YANG_ARGUMENT:
2569 return LYEXT_SUBSTMT_ARGUMENT;
2570 case YANG_BASE:
2571 return LYEXT_SUBSTMT_BASE;
2572 case YANG_BELONGS_TO:
2573 return LYEXT_SUBSTMT_BELONGSTO;
2574 case YANG_CONTACT:
2575 return LYEXT_SUBSTMT_CONTACT;
2576 case YANG_DEFAULT:
2577 return LYEXT_SUBSTMT_DEFAULT;
2578 case YANG_DESCRIPTION:
2579 return LYEXT_SUBSTMT_DESCRIPTION;
2580 case YANG_ERROR_APP_TAG:
2581 return LYEXT_SUBSTMT_ERRTAG;
2582 case YANG_ERROR_MESSAGE:
2583 return LYEXT_SUBSTMT_ERRMSG;
2584 case YANG_KEY:
2585 return LYEXT_SUBSTMT_KEY;
2586 case YANG_NAMESPACE:
2587 return LYEXT_SUBSTMT_NAMESPACE;
2588 case YANG_ORGANIZATION:
2589 return LYEXT_SUBSTMT_ORGANIZATION;
2590 case YANG_PATH:
2591 return LYEXT_SUBSTMT_PATH;
2592 case YANG_PREFIX:
2593 return LYEXT_SUBSTMT_PREFIX;
2594 case YANG_PRESENCE:
2595 return LYEXT_SUBSTMT_PRESENCE;
2596 case YANG_REFERENCE:
2597 return LYEXT_SUBSTMT_REFERENCE;
2598 case YANG_REVISION_DATE:
2599 return LYEXT_SUBSTMT_REVISIONDATE;
2600 case YANG_UNITS:
2601 return LYEXT_SUBSTMT_UNITS;
2602 case YANG_VALUE:
2603 return LYEXT_SUBSTMT_VALUE;
2604 case YANG_YANG_VERSION:
2605 return LYEXT_SUBSTMT_VERSION;
2606 case YANG_MODIFIER:
2607 return LYEXT_SUBSTMT_MODIFIER;
2608 case YANG_REQUIRE_INSTANCE:
2609 return LYEXT_SUBSTMT_REQINSTANCE;
2610 case YANG_YIN_ELEMENT:
2611 return LYEXT_SUBSTMT_YINELEM;
2612 case YANG_CONFIG:
2613 return LYEXT_SUBSTMT_CONFIG;
2614 case YANG_MANDATORY:
2615 return LYEXT_SUBSTMT_MANDATORY;
2616 case YANG_ORDERED_BY:
2617 return LYEXT_SUBSTMT_ORDEREDBY;
2618 case YANG_STATUS:
2619 return LYEXT_SUBSTMT_STATUS;
2620 case YANG_FRACTION_DIGITS:
2621 return LYEXT_SUBSTMT_FRACDIGITS;
2622 case YANG_MAX_ELEMENTS:
2623 return LYEXT_SUBSTMT_MAX;
2624 case YANG_MIN_ELEMENTS:
2625 return LYEXT_SUBSTMT_MIN;
2626 case YANG_POSITION:
2627 return LYEXT_SUBSTMT_POSITION;
2628 case YANG_UNIQUE:
2629 return LYEXT_SUBSTMT_UNIQUE;
2630 case YANG_IF_FEATURE:
2631 return LYEXT_SUBSTMT_IFFEATURE;
2632 default:
2633 return LYEXT_SUBSTMT_SELF;
2634 }
2635}
2636
David Sedlákc5b20842019-08-13 10:18:31 +02002637/**
2638 * @brief map keyword to keyword-group.
2639 *
2640 * @param[in] ctx YIN parser context used for logging.
2641 * @param[in] kw Keyword that is child of module or submodule.
2642 * @param[out] group Group of keyword.
2643 *
2644 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2645 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002646static LY_ERR
2647kw2kw_group(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_module_stmt *group)
2648{
2649 switch (kw) {
2650 /* module header */
2651 case YANG_NONE:
2652 case YANG_NAMESPACE:
2653 case YANG_PREFIX:
2654 case YANG_BELONGS_TO:
2655 case YANG_YANG_VERSION:
2656 *group = Y_MOD_MODULE_HEADER;
2657 break;
2658 /* linkage */
2659 case YANG_INCLUDE:
2660 case YANG_IMPORT:
2661 *group = Y_MOD_LINKAGE;
2662 break;
2663 /* meta */
2664 case YANG_ORGANIZATION:
2665 case YANG_CONTACT:
2666 case YANG_DESCRIPTION:
2667 case YANG_REFERENCE:
2668 *group = Y_MOD_META;
2669 break;
2670 /* revision */
2671 case YANG_REVISION:
2672 *group = Y_MOD_REVISION;
2673 break;
2674 /* body */
2675 case YANG_ANYDATA:
2676 case YANG_ANYXML:
2677 case YANG_AUGMENT:
2678 case YANG_CHOICE:
2679 case YANG_CONTAINER:
2680 case YANG_DEVIATION:
2681 case YANG_EXTENSION:
2682 case YANG_FEATURE:
2683 case YANG_GROUPING:
2684 case YANG_IDENTITY:
2685 case YANG_LEAF:
2686 case YANG_LEAF_LIST:
2687 case YANG_LIST:
2688 case YANG_NOTIFICATION:
2689 case YANG_RPC:
2690 case YANG_TYPEDEF:
2691 case YANG_USES:
2692 case YANG_CUSTOM:
2693 *group = Y_MOD_BODY;
2694 break;
2695 default:
2696 LOGINT(ctx->xml_ctx.ctx);
2697 return LY_EINT;
2698 }
2699
2700 return LY_SUCCESS;
2701}
2702
David Sedlákc5b20842019-08-13 10:18:31 +02002703/**
2704 * @brief Check if relative order of two keywords is valid.
2705 *
2706 * @param[in] ctx YIN parser context used for logging.
2707 * @param[in] kw Current keyword.
2708 * @param[in] next_kw Next keyword.
2709 * @param[in] parrent Identification of parrent element, can be se to to YANG_MODULE of YANG_SUBMODULE,
2710 * because relative order is required only in module and submodule sub-elements, used for logging.
2711 *
2712 * @return LY_SUCCESS on succes and LY_EVALID if relative order is invalid.
2713 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002714static LY_ERR
2715yin_check_relative_order(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_keyword next_kw, enum yang_keyword parrent)
2716{
2717 assert(parrent == YANG_MODULE || parrent == YANG_SUBMODULE);
2718 enum yang_module_stmt gr, next_gr;
2719
2720 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2721 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2722
2723 if (gr > next_gr) {
2724 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2725 return LY_EVALID;
2726 }
2727
2728 return LY_SUCCESS;
2729}
2730
David Sedlákd6e56892019-07-01 15:40:24 +02002731LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002732yin_parse_content(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info, signed char subelem_info_size,
David Sedlák3ffbc522019-07-02 17:49:28 +02002733 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 +02002734{
2735 LY_ERR ret = LY_SUCCESS;
David Sedlák8e7bda82019-07-16 17:57:50 +02002736 char *out = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +02002737 const char *prefix, *name;
2738 size_t out_len = 0, prefix_len, name_len;
David Sedlák8e7bda82019-07-16 17:57:50 +02002739 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002740 struct yin_arg_record *attrs = NULL;
David Sedláke6cd89e2019-08-07 12:46:02 +02002741 enum yang_keyword kw = YANG_NONE, last_kw = YANG_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002742 struct yin_subelement *subelem = NULL;
David Sedlák374d2b32019-07-17 15:06:55 +02002743 struct lysp_type *type, *nested_type;
David Sedlák09e18c92019-07-18 11:17:11 +02002744
David Sedlákb0faad82019-07-04 14:28:59 +02002745 assert(is_ordered(subelem_info, subelem_info_size));
David Sedlákd6e56892019-07-01 15:40:24 +02002746
David Sedlákda8ffa32019-07-08 14:17:10 +02002747 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2748 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002749 /* current element has subelements as content */
2750 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002751 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákc5b20842019-08-13 10:18:31 +02002752 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákd6e56892019-07-01 15:40:24 +02002753 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +02002754 if (!name) {
David Sedlákd6e56892019-07-01 15:40:24 +02002755 /* end of current element reached */
2756 break;
2757 }
David Sedlák1af868e2019-07-17 17:03:14 +02002758 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002759 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6cd89e2019-08-07 12:46:02 +02002760 last_kw = kw;
David Sedlákc5b20842019-08-13 10:18:31 +02002761 kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002762
2763 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002764 subelem = get_record(kw, subelem_info_size, subelem_info);
2765 if (!subelem) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002766 if (current_element == YANG_DEVIATE && isdevsub(kw)) {
2767 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2768 } else {
David Sedlákc5b20842019-08-13 10:18:31 +02002769 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(current_element));
David Sedlák4ffcec82019-07-25 15:10:21 +02002770 }
David Sedlákd6e56892019-07-01 15:40:24 +02002771 ret = LY_EVALID;
2772 goto cleanup;
2773 }
2774
David Sedláke6cd89e2019-08-07 12:46:02 +02002775 if (current_element == YANG_MODULE || current_element == YANG_SUBMODULE) {
2776 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2777 LY_CHECK_GOTO(ret, cleanup);
2778 }
David Sedlák5f8191e2019-07-08 16:35:52 +02002779
David Sedlák4ffcec82019-07-25 15:10:21 +02002780 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002781 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002782 /* subelement uniquenes */
David Sedlák1538a842019-08-08 15:38:51 +02002783 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +02002784 return LY_EVALID;
2785 }
David Sedlák1af868e2019-07-17 17:03:14 +02002786 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002787 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002788 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002789 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002790 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002791 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002792 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002793 if (ctx->mod_version < 2) {
David Sedlák1538a842019-08-08 15:38:51 +02002794 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák9bb1c042019-07-22 16:45:37 +02002795 ret = LY_EVALID;
2796 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002797 }
2798 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002799 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002800 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002801
David Sedlákd6e56892019-07-01 15:40:24 +02002802 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002803 /* call responsible function */
David Sedlákd6e56892019-07-01 15:40:24 +02002804 case YANG_CUSTOM:
David Sedlákc5b20842019-08-13 10:18:31 +02002805 ret = yin_parse_extension_instance(ctx, attrs, data, name2fullname(name, prefix_len),
2806 namelen2fulllen(name_len, prefix_len),
David Sedlák1af868e2019-07-17 17:03:14 +02002807 kw2lyext_substmt(current_element),
2808 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002809 break;
2810 case YANG_ACTION:
David Sedlákeaa45792019-07-24 15:25:01 +02002811 case YANG_RPC:
David Sedlák6881b512019-08-13 12:52:00 +02002812 ret = yin_parse_action(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002813 break;
2814 case YANG_ANYDATA:
David Sedlákd6e56892019-07-01 15:40:24 +02002815 case YANG_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002816 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002817 break;
2818 case YANG_ARGUMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002819 ret = yin_parse_argument_element(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002820 break;
2821 case YANG_AUGMENT:
David Sedlák6881b512019-08-13 12:52:00 +02002822 ret = yin_parse_augment(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002823 break;
2824 case YANG_BASE:
David Sedláka62750b2019-07-16 11:21:31 +02002825 if (current_element == YANG_TYPE) {
David Sedlák1af868e2019-07-17 17:03:14 +02002826 type = (struct lysp_type *)subelem->dest;
2827 ret = yin_parse_simple_elements(ctx, attrs, data, kw, &type->bases, YIN_ARG_NAME,
David Sedlák292763b2019-07-09 11:10:53 +02002828 Y_PREF_IDENTIF_ARG, exts);
2829 type->flags |= LYS_SET_BASE;
David Sedláka62750b2019-07-16 11:21:31 +02002830 } else if (current_element == YANG_IDENTITY) {
David Sedlák1af868e2019-07-17 17:03:14 +02002831 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedlák292763b2019-07-09 11:10:53 +02002832 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts);
2833 } else {
2834 LOGINT(ctx->xml_ctx.ctx);
2835 ret = LY_EINT;
2836 }
David Sedlákd6e56892019-07-01 15:40:24 +02002837 break;
2838 case YANG_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002839 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002840 break;
2841 case YANG_BIT:
David Sedlák43801c92019-08-05 15:58:54 +02002842 ret = yin_parse_bit(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002843 break;
2844 case YANG_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002845 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002846 break;
2847 case YANG_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002848 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002849 break;
2850 case YANG_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02002851 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002852 break;
2853 case YANG_CONTACT:
David Sedlák619db942019-07-03 14:47:30 +02002854 case YANG_DESCRIPTION:
2855 case YANG_ORGANIZATION:
2856 case YANG_REFERENCE:
David Sedlákdf2a9732019-08-07 13:23:16 +02002857 ret = yin_parse_meta_element(ctx, attrs, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002858 break;
2859 case YANG_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02002860 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002861 break;
2862 case YANG_DEFAULT:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002863 if (subelem->flags & YIN_SUBELEM_UNIQUE) {
2864 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
2865 YIN_ARG_VALUE, Y_STR_ARG, exts);
2866 } else {
2867 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
2868 YIN_ARG_VALUE, Y_STR_ARG, exts);
2869 }
David Sedlákd6e56892019-07-01 15:40:24 +02002870 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002871 case YANG_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002872 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002873 break;
2874 case YANG_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02002875 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002876 break;
David Sedlák43801c92019-08-05 15:58:54 +02002877 case YANG_ENUM:
2878 ret = yin_parse_enum(ctx, attrs, data, (struct lysp_type *)subelem->dest);
2879 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002880 case YANG_ERROR_APP_TAG:
David Sedlák1af868e2019-07-17 17:03:14 +02002881 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002882 YIN_ARG_VALUE, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002883 break;
2884 case YANG_ERROR_MESSAGE:
David Sedlákdf2a9732019-08-07 13:23:16 +02002885 ret = yin_parse_err_msg_element(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002886 break;
2887 case YANG_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002888 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002889 break;
2890 case YANG_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02002891 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002892 break;
2893 case YANG_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002894 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002895 break;
2896 case YANG_GROUPING:
David Sedlák6881b512019-08-13 12:52:00 +02002897 ret = yin_parse_grouping(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002898 break;
2899 case YANG_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02002900 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002901 break;
2902 case YANG_IF_FEATURE:
David Sedlák1af868e2019-07-17 17:03:14 +02002903 ret = yin_parse_simple_elements(ctx, attrs, data, kw,
2904 (const char ***)subelem->dest, YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002905 break;
2906 case YANG_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02002907 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002908 break;
2909 case YANG_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02002910 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002911 break;
2912 case YANG_INPUT:
David Sedlák05404f62019-07-24 14:11:53 +02002913 case YANG_OUTPUT:
2914 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002915 break;
2916 case YANG_KEY:
David Sedlák12470a82019-07-19 13:44:36 +02002917 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2918 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002919 break;
2920 case YANG_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02002921 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002922 break;
2923 case YANG_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002924 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002925 break;
2926 case YANG_LENGTH:
David Sedlák1af868e2019-07-17 17:03:14 +02002927 type = (struct lysp_type *)subelem->dest;
David Sedlák438ae432019-07-11 15:36:54 +02002928 type->length = calloc(1, sizeof *type->length);
2929 LY_CHECK_ERR_GOTO(!type->length, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002930 ret = yin_parse_restriction(ctx, attrs, data, kw, type->length);
David Sedlák438ae432019-07-11 15:36:54 +02002931 type->flags |= LYS_SET_LENGTH;
David Sedlákd6e56892019-07-01 15:40:24 +02002932 break;
2933 case YANG_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02002934 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002935 break;
2936 case YANG_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02002937 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002938 break;
2939 case YANG_MAX_ELEMENTS:
David Sedlákd6e56892019-07-01 15:40:24 +02002940 case YANG_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02002941 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002942 break;
2943 case YANG_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02002944 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002945 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002946 case YANG_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02002947 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002948 break;
2949 case YANG_NAMESPACE:
David Sedlák1af868e2019-07-17 17:03:14 +02002950 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002951 YIN_ARG_URI, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002952 break;
2953 case YANG_NOTIFICATION:
David Sedlák6881b512019-08-13 12:52:00 +02002954 ret = yin_parse_notification(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002955 break;
2956 case YANG_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02002957 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002958 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002959 case YANG_PATH:
David Sedlák1af868e2019-07-17 17:03:14 +02002960 type = (struct lysp_type *)subelem->dest;
2961 ret = yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
David Sedlákd1144562019-08-06 12:36:14 +02002962 YIN_ARG_VALUE, Y_STR_ARG, &type->exts);
David Sedlák58979872019-07-12 11:42:43 +02002963 type->flags |= LYS_SET_PATH;
David Sedlákd6e56892019-07-01 15:40:24 +02002964 break;
2965 case YANG_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02002966 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002967 break;
David Sedlák5545f5d2019-07-11 11:55:16 +02002968 case YANG_VALUE:
David Sedlákd6e56892019-07-01 15:40:24 +02002969 case YANG_POSITION:
David Sedlák1af868e2019-07-17 17:03:14 +02002970 ret = yin_parse_value_pos_element(ctx, attrs, data, kw,
2971 (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002972 break;
2973 case YANG_PREFIX:
David Sedlák1af868e2019-07-17 17:03:14 +02002974 ret = yin_parse_simple_element(ctx, attrs, data, kw,
2975 (const char **)subelem->dest, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002976 break;
2977 case YANG_PRESENCE:
David Sedlákcb39f642019-07-19 13:19:55 +02002978 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2979 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002980 break;
2981 case YANG_RANGE:
David Sedlák1af868e2019-07-17 17:03:14 +02002982 type = (struct lysp_type *)subelem->dest;
David Sedlákb7296dd2019-07-11 14:58:38 +02002983 type->range = calloc(1, sizeof *type->range);
David Sedlák66d7c842019-07-11 15:06:04 +02002984 LY_CHECK_ERR_GOTO(!type->range, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002985 ret = yin_parse_restriction(ctx, attrs, data, kw, type->range);
David Sedlák438ae432019-07-11 15:36:54 +02002986 type->flags |= LYS_SET_RANGE;
David Sedlákd6e56892019-07-01 15:40:24 +02002987 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002988 case YANG_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02002989 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002990 break;
2991 case YANG_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02002992 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002993 break;
2994 case YANG_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02002995 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002996 break;
2997 case YANG_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02002998 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002999 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003000 case YANG_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02003001 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003002 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003003 case YANG_TYPE:
David Sedlák4ffcec82019-07-25 15:10:21 +02003004 if (current_element == YANG_DEVIATE) {
3005 *(struct lysp_type **)subelem->dest = calloc(1, sizeof **(struct lysp_type **)subelem->dest);
3006 LY_CHECK_ERR_GOTO(!(*(struct lysp_type **)subelem->dest), LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
3007 type = *((struct lysp_type **)subelem->dest);
3008 } else {
3009 type = (struct lysp_type *)subelem->dest;
3010 }
David Sedlák374d2b32019-07-17 15:06:55 +02003011 /* type as child of another type */
David Sedlák374d2b32019-07-17 15:06:55 +02003012 if (current_element == YANG_TYPE) {
3013 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, type->types, nested_type, ret, cleanup);
David Sedlákc3da3ef2019-07-19 12:56:08 +02003014 type->flags |= LYS_SET_TYPE;
David Sedlák374d2b32019-07-17 15:06:55 +02003015 type = nested_type;
3016 }
David Sedlák1af868e2019-07-17 17:03:14 +02003017 ret = yin_parse_type(ctx, attrs, data, type);
David Sedlákd6e56892019-07-01 15:40:24 +02003018 break;
3019 case YANG_TYPEDEF:
David Sedlák6881b512019-08-13 12:52:00 +02003020 ret = yin_parse_typedef(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003021 break;
3022 case YANG_UNIQUE:
David Sedlák1af868e2019-07-17 17:03:14 +02003023 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02003024 YIN_ARG_TAG, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003025 break;
3026 case YANG_UNITS:
David Sedlák1af868e2019-07-17 17:03:14 +02003027 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02003028 YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003029 break;
3030 case YANG_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02003031 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003032 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003033 case YANG_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02003034 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003035 break;
3036 case YANG_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003037 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003038 break;
3039 case YANG_YIN_ELEMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02003040 ret = yin_parse_yin_element_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02003041 break;
3042 case YIN_TEXT:
David Sedlák3ffbc522019-07-02 17:49:28 +02003043 case YIN_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02003044 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02003045 break;
3046 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02003047 LOGINT(ctx->xml_ctx.ctx);
David Sedlák21f87cd2019-07-03 16:53:23 +02003048 return LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02003049 }
David Sedlák3ffbc522019-07-02 17:49:28 +02003050 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02003051 FREE_ARRAY(ctx, attrs, free_arg_rec);
3052 attrs = NULL;
3053 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02003054 }
3055 } else {
3056 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02003057 /* save text content, if text_content isn't set, it's just ignored */
David Sedlákc5b20842019-08-13 10:18:31 +02003058 /* no resources are allocated in this branch, no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02003059 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02003060 if (text_content) {
3061 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003062 *text_content = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák3ffbc522019-07-02 17:49:28 +02003063 if (!*text_content) {
3064 free(out);
3065 return LY_EMEM;
3066 }
3067 } else {
3068 if (out_len == 0) {
David Sedlák99295322019-07-17 11:34:18 +02003069 *text_content = lydict_insert(ctx->xml_ctx.ctx, "", 0);
David Sedlák3ffbc522019-07-02 17:49:28 +02003070 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003071 *text_content = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák3ffbc522019-07-02 17:49:28 +02003072 }
3073 }
3074 }
David Sedlákd6e56892019-07-01 15:40:24 +02003075 /* load closing element */
David Sedlákc5b20842019-08-13 10:18:31 +02003076 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákd6e56892019-07-01 15:40:24 +02003077 }
3078 }
David Sedlák8b754462019-07-25 16:22:13 +02003079 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3080 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003081
3082cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02003083 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02003084 return ret;
3085}
3086
David Sedlák619db942019-07-03 14:47:30 +02003087LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02003088yin_parse_extension_instance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, const char *ext_name,
David Sedlák619db942019-07-03 14:47:30 +02003089 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003090{
3091 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003092 char *out;
3093 const char *name, *prefix;
3094 size_t out_len, prefix_len, name_len;
3095 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003096 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003097 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
3098 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003099
David Sedlákda8ffa32019-07-08 14:17:10 +02003100 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003101
3102 e->yin = 0;
3103 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02003104 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02003105 e->insubstmt = subelem;
3106 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003107 e->yin |= LYS_YIN;
3108
David Sedlákb1a78352019-06-28 16:16:29 +02003109 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02003110 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02003111 if (!iter->prefix) {
3112 new_subelem = calloc(1, sizeof(*new_subelem));
3113 if (!e->child) {
3114 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003115 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003116 last_subelem->next = new_subelem;
3117 }
3118 last_subelem = new_subelem;
3119
3120 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003121 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
3122 LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003123 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003124 last_subelem->arg = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
3125 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003126 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003127 last_subelem->arg = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
3128 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003129 }
3130 }
3131 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003132
David Sedlákf250ecf2019-07-01 11:02:05 +02003133 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003134 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3135 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003136 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003137 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3138 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02003139 if (!name) {
3140 /* end of extension instance reached */
3141 break;
3142 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003143 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02003144 if (!e->child) {
3145 e->child = new_subelem;
3146 } else {
3147 last_subelem->next = new_subelem;
3148 }
3149 last_subelem = new_subelem;
3150 }
David Sedlák555c7202019-07-04 12:14:12 +02003151 } else {
3152 /* save text content */
3153 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003154 e->argument = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák555c7202019-07-04 12:14:12 +02003155 if (!e->argument) {
3156 free(out);
3157 return LY_EMEM;
3158 }
3159 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003160 e->argument = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02003161 LY_CHECK_RET(!e->argument, LY_EMEM);
3162 }
David Sedlákda8ffa32019-07-08 14:17:10 +02003163 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlák555c7202019-07-04 12:14:12 +02003164 LY_CHECK_RET(name, LY_EINT);
David Sedlákb1a78352019-06-28 16:16:29 +02003165 }
David Sedlákb1a78352019-06-28 16:16:29 +02003166 }
3167
3168 return LY_SUCCESS;
3169}
3170
3171LY_ERR
David Sedlák4ffcec82019-07-25 15:10:21 +02003172yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char **data,
3173 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02003174{
3175 LY_ERR ret = LY_SUCCESS;
3176 const char *temp_prefix, *temp_name;
3177 char *out = NULL;
David Sedlák4ffcec82019-07-25 15:10:21 +02003178 size_t out_len, temp_name_len, temp_prefix_len, prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02003179 int dynamic;
3180 struct yin_arg_record *subelem_args = NULL;
3181 struct lysp_stmt *last = NULL, *new = NULL;
3182
3183 /* allocate new structure for element */
3184 *element = calloc(1, sizeof(**element));
David Sedlákda8ffa32019-07-08 14:17:10 +02003185 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, name, name_len);
3186 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003187
3188 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +02003189 /* load attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +02003190 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákb1a78352019-06-28 16:16:29 +02003191 /* add new element to linked-list */
3192 new = calloc(1, sizeof(*last));
David Sedlákda8ffa32019-07-08 14:17:10 +02003193 LY_CHECK_ERR_GOTO(ret, LOGMEM(ctx->xml_ctx.ctx), err);
David Sedlákb1a78352019-06-28 16:16:29 +02003194 if (!(*element)->child) {
3195 /* save first */
3196 (*element)->child = new;
3197 } else {
3198 last->next = new;
3199 }
3200 last = new;
3201
3202 last->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003203 ret = lyxml_get_attribute(&ctx->xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
David Sedlákb1a78352019-06-28 16:16:29 +02003204 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003205 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003206 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003207 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
3208 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003209 /* attributes with prefix are ignored */
3210 if (!temp_prefix) {
3211 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003212 last->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlákb1a78352019-06-28 16:16:29 +02003213 if (!last->arg) {
3214 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02003215 LOGMEM(ctx->xml_ctx.ctx);
David Sedlákb1a78352019-06-28 16:16:29 +02003216 ret = LY_EMEM;
3217 goto err;
3218 }
3219 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003220 last->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
3221 LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003222 }
3223 }
3224 }
3225
3226 /* parse content of element */
David Sedlákda8ffa32019-07-08 14:17:10 +02003227 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003228 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003229 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákb1a78352019-06-28 16:16:29 +02003230 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003231 ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
David Sedlákb1a78352019-06-28 16:16:29 +02003232 LY_CHECK_GOTO(ret, err);
3233 if (!name) {
3234 /* end of element reached */
3235 break;
3236 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003237 ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, data, &last->next);
David Sedlákb1a78352019-06-28 16:16:29 +02003238 LY_CHECK_GOTO(ret, err);
3239 last = last->next;
3240 }
3241 } else {
3242 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +02003243 if (out_len != 0) {
3244 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003245 (*element)->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák5392a212019-07-01 09:19:10 +02003246 if (!(*element)->arg) {
3247 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02003248 LOGMEM(ctx->xml_ctx.ctx);
David Sedlák5392a212019-07-01 09:19:10 +02003249 ret = LY_EMEM;
3250 goto err;
3251 }
3252 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003253 (*element)->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
3254 LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003255 }
David Sedlákb1a78352019-06-28 16:16:29 +02003256 }
3257 /* read closing tag */
David Sedlákda8ffa32019-07-08 14:17:10 +02003258 ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
David Sedlákb1a78352019-06-28 16:16:29 +02003259 LY_CHECK_GOTO(ret, err);
3260 }
3261
David Sedlákda8ffa32019-07-08 14:17:10 +02003262 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlákb1a78352019-06-28 16:16:29 +02003263 return LY_SUCCESS;
3264
3265err:
David Sedlákda8ffa32019-07-08 14:17:10 +02003266 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003267 return ret;
3268}
3269
3270LY_ERR
David Sedlák4f03b932019-07-26 13:01:47 +02003271yin_parse_mod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003272{
David Sedlák81497a32019-08-13 16:56:26 +02003273 LY_ERR ret = LY_SUCCESS;
3274 struct yin_subelement *subelems = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003275
David Sedlák81497a32019-08-13 16:56:26 +02003276 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, YANG_MODULE));
3277 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
3278 YANG_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3279 YANG_ANYXML, &mod->data, 0,
3280 YANG_AUGMENT, &mod->augments, 0,
3281 YANG_CHOICE, &mod->data, 0,
3282 YANG_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3283 YANG_CONTAINER, &mod->data, 0,
3284 YANG_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3285 YANG_DEVIATION, &mod->deviations, 0,
3286 YANG_EXTENSION, &mod->extensions, 0,
3287 YANG_FEATURE, &mod->features, 0,
3288 YANG_GROUPING, &mod->groupings, 0,
3289 YANG_IDENTITY, &mod->identities, 0,
3290 YANG_IMPORT, mod->mod->prefix, &mod->imports, 0,
3291 YANG_INCLUDE, mod->mod->name, &mod->includes, 0,
3292 YANG_LEAF, &mod->data, 0,
3293 YANG_LEAF_LIST, &mod->data, 0,
3294 YANG_LIST, &mod->data, 0,
3295 YANG_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3296 YANG_NOTIFICATION, &mod->notifs, 0,
3297 YANG_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3298 YANG_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3299 YANG_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3300 YANG_REVISION, &mod->revs, 0,
3301 YANG_RPC, &mod->rpcs, 0,
3302 YANG_TYPEDEF, &mod->typedefs, 0,
3303 YANG_USES, &mod->data, 0,
3304 YANG_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3305 YANG_CUSTOM, NULL, 0
3306 ));
3307
3308 ret = yin_parse_content(ctx, subelems, 28, data, YANG_MODULE, NULL, &mod->exts);
3309 subelems_deallocator(28, subelems);
3310
3311 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003312}
3313
3314LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003315yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3316{
David Sedlák81497a32019-08-13 16:56:26 +02003317 LY_ERR ret = LY_SUCCESS;
3318 struct yin_subelement *subelems = NULL;
David Sedlák298ff6d2019-07-26 14:29:03 +02003319
David Sedlák81497a32019-08-13 16:56:26 +02003320 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, YANG_SUBMODULE));
3321 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
3322 YANG_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3323 YANG_ANYXML, &submod->data, 0,
3324 YANG_AUGMENT, &submod->augments, 0,
3325 YANG_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3326 YANG_CHOICE, &submod->data, 0,
3327 YANG_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3328 YANG_CONTAINER, &submod->data, 0,
3329 YANG_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3330 YANG_DEVIATION, &submod->deviations, 0,
3331 YANG_EXTENSION, &submod->extensions, 0,
3332 YANG_FEATURE, &submod->features, 0,
3333 YANG_GROUPING, &submod->groupings, 0,
3334 YANG_IDENTITY, &submod->identities, 0,
3335 YANG_IMPORT, submod->prefix, &submod->imports, 0,
3336 YANG_INCLUDE, submod->name, &submod->includes, 0,
3337 YANG_LEAF, &submod->data, 0,
3338 YANG_LEAF_LIST, &submod->data, 0,
3339 YANG_LIST, &submod->data, 0,
3340 YANG_NOTIFICATION, &submod->notifs, 0,
3341 YANG_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3342 YANG_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3343 YANG_REVISION, &submod->revs, 0,
3344 YANG_RPC, &submod->rpcs, 0,
3345 YANG_TYPEDEF, &submod->typedefs, 0,
3346 YANG_USES, &submod->data, 0,
3347 YANG_YANG_VERSION, &submod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3348 YANG_CUSTOM, NULL, 0
3349 ));
3350
3351 ret = yin_parse_content(ctx, subelems, 27, data, YANG_SUBMODULE, NULL, &submod->exts);
3352 subelems_deallocator(27, subelems);
3353
3354 return ret;
David Sedlák298ff6d2019-07-26 14:29:03 +02003355}
3356
3357LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02003358yin_parse_submodule(struct yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, struct lys_parser_ctx *main_ctx, const char *data, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003359{
3360 enum yang_keyword kw = YANG_NONE;
3361 LY_ERR ret = LY_SUCCESS;
3362 const char *prefix, *name;
3363 size_t prefix_len, name_len;
3364 struct yin_arg_record *attrs = NULL;
3365 struct lysp_submodule *mod_p = NULL;
3366
3367 /* create context */
3368 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003369 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003370 (*yin_ctx)->xml_ctx.ctx = ctx;
3371 (*yin_ctx)->xml_ctx.line = 1;
3372
David Sedlák1b623122019-08-05 15:27:49 +02003373 /* map the typedefs and groupings list from main context to the submodule's context */
3374 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3375 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3376
David Sedlák8985a142019-07-31 16:43:06 +02003377 /* check submodule */
3378 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3379 LY_CHECK_GOTO(ret, cleanup);
3380 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3381 LY_CHECK_GOTO(ret, cleanup);
3382 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
3383
3384 if (kw == YANG_MODULE) {
3385 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3386 ret = LY_EINVAL;
3387 goto cleanup;
3388 } else if (kw != YANG_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003389 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003390 ret = LY_EVALID;
3391 goto cleanup;
3392 }
3393
3394 mod_p = calloc(1, sizeof *mod_p);
3395 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3396 mod_p->parsing = 1;
3397
3398 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3399 LY_CHECK_GOTO(ret, cleanup);
3400
David Sedlák6d781b62019-08-02 15:22:52 +02003401 name = NULL;
3402 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3403 const char *temp_data = data;
3404 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3405 data = temp_data;
3406 }
3407 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
David Sedlák1538a842019-08-08 15:38:51 +02003408 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, data, strlen(data) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003409 ret = LY_EVALID;
3410 goto cleanup;
3411 }
3412
David Sedlák8985a142019-07-31 16:43:06 +02003413 mod_p->parsing = 0;
3414 *submod = mod_p;
3415
3416cleanup:
3417 if (ret) {
3418 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003419 yin_parser_ctx_free(*yin_ctx);
3420 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003421 }
3422
3423 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3424 return ret;
3425}
3426
3427LY_ERR
3428yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003429{
David Sedláke4889912018-11-02 09:52:40 +01003430 LY_ERR ret = LY_SUCCESS;
3431 enum yang_keyword kw = YANG_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003432 struct lysp_module *mod_p = NULL;
3433 const char *prefix, *name;
3434 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003435 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003436
David Sedlák8985a142019-07-31 16:43:06 +02003437 /* create context */
3438 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003439 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003440 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
3441 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003442
David Sedlák8985a142019-07-31 16:43:06 +02003443 /* check module */
3444 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003445 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003446 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003447 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003448 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
David Sedláke4889912018-11-02 09:52:40 +01003449 if (kw == YANG_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003450 LOGERR(mod->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
David Sedlák3017da42019-02-15 09:48:04 +01003451 ret = LY_EINVAL;
3452 goto cleanup;
3453 } else if (kw != YANG_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003454 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003455 ret = LY_EVALID;
3456 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003457 }
3458
David Sedlák3017da42019-02-15 09:48:04 +01003459 /* allocate module */
3460 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003461 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003462 mod_p->mod = mod;
3463 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003464
David Sedlák00250342019-06-21 14:19:39 +02003465 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003466 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003467 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003468
David Sedlák1b623122019-08-05 15:27:49 +02003469 /* check trailing characters */
David Sedlák6d781b62019-08-02 15:22:52 +02003470 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3471 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3472 }
3473 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
David Sedlák1538a842019-08-08 15:38:51 +02003474 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, data, strlen(data) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003475
3476 ret = LY_EVALID;
3477 goto cleanup;
3478 }
3479
David Sedlák3017da42019-02-15 09:48:04 +01003480 mod_p->parsing = 0;
3481 mod->parsed = mod_p;
3482
3483cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003484 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003485 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003486 yin_parser_ctx_free(*yin_ctx);
3487 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003488 }
David Sedlák8985a142019-07-31 16:43:06 +02003489 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003490 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003491}