blob: 8e2dbfc90155380475ebebfddc5b905e86544646 [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ák6542aed2019-08-14 10:47:43 +0200513 * @brief Parse path 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] kw Type of current element.
519 * @param[out] type Type structure to store parsed value, flags and extension instances.
520 *
521 * @return LY_ERR values.
522 */
523static LY_ERR
524yin_parse_path(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
525 struct lysp_type *type)
526{
527 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
528 YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
529 type->flags |= LYS_SET_PATH;
530
531 return LY_SUCCESS;
532}
533
534/**
David Sedlákd3983112019-07-12 11:20:56 +0200535 * @brief Parse pattern element.
536 *
537 * @param[in,out] ctx Yin parser context for logging and to store current state.
538 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
539 * @param[in,out] data Data to read from, always moved to currently handled character.
540 * @param[in,out] patterns Restrictions to add to.
541 *
542 * @return LY_ERR values.
543 */
544static LY_ERR
545yin_parse_pattern(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
546 struct lysp_type *type)
547{
548 const char *real_value = NULL;
549 char *saved_value = NULL;
550 struct lysp_restr *restr;
551
552 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->patterns, restr, LY_EMEM);
553 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &real_value, Y_STR_ARG, YANG_PATTERN));
554 size_t len = strlen(real_value);
555
556 saved_value = malloc(len + 2);
557 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
558 memmove(saved_value + 1, real_value, len);
559 FREE_STRING(ctx->xml_ctx.ctx, real_value);
560 saved_value[0] = 0x06;
561 saved_value[len + 1] = '\0';
562 restr->arg = lydict_insert_zc(ctx->xml_ctx.ctx, saved_value);
563 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
564 type->flags |= LYS_SET_PATTERN;
565
566 struct yin_subelement subelems[6] = {
567 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
568 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
569 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
570 {YANG_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
571 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
572 {YANG_CUSTOM, NULL, 0}
573 };
574 return yin_parse_content(ctx, subelems, 6, data, YANG_PATTERN, NULL, &restr->exts);
575}
576
David Sedlákc5b20842019-08-13 10:18:31 +0200577/**
578 * @brief Parse fraction-digits element.
579 *
580 * @param[in,out] ctx Yin parser context for logging and to store current state.
581 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
582 * @param[in,out] data Data to read from, always moved to currently handled character.
583 * @param[in,out] type Type structure to store value, flags and extension instances.
584 *
585 * @return LY_ERR values.
586 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200587static LY_ERR
588yin_parse_fracdigits(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
589 struct lysp_type *type)
590{
591 const char *temp_val = NULL;
592 char *ptr;
593 unsigned long int num;
594
595 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_FRACTION_DIGITS));
596
597 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200598 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200599 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
600 return LY_EVALID;
601 }
602
603 errno = 0;
604 num = strtoul(temp_val, &ptr, 10);
605 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200606 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200607 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
608 return LY_EVALID;
609 }
610 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200611 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200612 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
613 return LY_EVALID;
614 }
David Sedlák2ab5d8e2019-07-16 11:19:41 +0200615 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200616 type->fraction_digits = num;
617 type->flags |= LYS_SET_FRDIGITS;
618 struct yin_subelement subelems[1] = {
David Sedlákd1144562019-08-06 12:36:14 +0200619 {YANG_CUSTOM, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200620 };
621 return yin_parse_content(ctx, subelems, 1, data, YANG_FRACTION_DIGITS, NULL, &type->exts);
622}
623
David Sedlák07869a52019-07-12 14:28:19 +0200624/**
David Sedlák43801c92019-08-05 15:58:54 +0200625 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200626 *
627 * @param[in,out] ctx YIN parser context for logging and to store current state.
628 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
629 * @param[in,out] data Data to read from, always moved to currently handled character.
630 * @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 +0200631 * @param[in,out] type Type structure to store enum value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200632 *
633 * @return LY_ERR values.
634 */
David Sedlákca36c422019-07-12 12:47:55 +0200635static LY_ERR
David Sedlák43801c92019-08-05 15:58:54 +0200636yin_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 +0200637{
David Sedlák07869a52019-07-12 14:28:19 +0200638 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200639
David Sedlák43801c92019-08-05 15:58:54 +0200640 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->enums, en, LY_EMEM);
641 type->flags |= LYS_SET_ENUM;
642 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_ENUM));
643 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
644 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
645 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200646
647 struct yin_subelement subelems[6] = {
David Sedlák07869a52019-07-12 14:28:19 +0200648 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
649 {YANG_IF_FEATURE, &en->iffeatures, 0},
David Sedlák07869a52019-07-12 14:28:19 +0200650 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
651 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
David Sedlák43801c92019-08-05 15:58:54 +0200652 {YANG_VALUE, en, YIN_SUBELEM_UNIQUE},
David Sedlákca36c422019-07-12 12:47:55 +0200653 {YANG_CUSTOM, NULL, 0}
654 };
David Sedlák43801c92019-08-05 15:58:54 +0200655 return yin_parse_content(ctx, subelems, 6, data, YANG_ENUM, NULL, &en->exts);
656}
657
658/**
659 * @brief Parse bit element.
660 *
661 * @param[in,out] ctx YIN parser context for logging and to store current state.
662 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
663 * @param[in,out] data Data to read from, always moved to currently handled character.
664 * @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 +0200665 * @param[in,out] type Type structure to store bit value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200666 *
667 * @return LY_ERR values.
668 */
669static LY_ERR
670yin_parse_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
671 struct lysp_type *type)
672{
673 struct lysp_type_enum *en;
674
675 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->bits, en, LY_EMEM);
676 type->flags |= LYS_SET_BIT;
677 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_BIT));
678 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
679
680 struct yin_subelement subelems[6] = {
681 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
682 {YANG_IF_FEATURE, &en->iffeatures, 0},
683 {YANG_POSITION, en, YIN_SUBELEM_UNIQUE},
684 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
685 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
686 {YANG_CUSTOM, NULL, 0}
687 };
688 return yin_parse_content(ctx, subelems, 6, data, YANG_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200689}
690
David Sedlákd3983112019-07-12 11:20:56 +0200691/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200692 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
693 * more instances, such as base or if-feature.
694 *
695 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200696 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200697 * @param[in,out] data Data to read from, always moved to currently handled character.
698 * @param[in] kw Type of current element.
699 * @param[out] values Parsed values to add to.
700 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200701 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlák5f8191e2019-07-08 16:35:52 +0200702 * @param[in,out] exts Extension instance to add to.
703 *
704 * @return LY_ERR values.
705 */
706static LY_ERR
707yin_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 +0200708 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 +0200709{
710 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200711 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200712 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200713 struct yin_subelement subelems[1] = {
714 {YANG_CUSTOM, &index, 0}
715 };
716
David Sedlák1f90d252019-07-10 17:09:32 +0200717 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200718
719 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
720}
721
722/**
David Sedlák6542aed2019-08-14 10:47:43 +0200723 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
724 *
725 * @param[in,out] ctx YIN parser context for logging and to store current state.
726 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
727 * @param[in,out] data Data to read from, always moved to currently handled character.
728 * @param[in] kw Type of current element.
729 * @param[out] values Parsed values to add to.
730 * @param[in] arg_type Expected type of attribute.
731 * @param[in] arg_val_type Type of expected value of attribute.
732 * @param[in,out] exts Extension instance to add to.
733 *
734 * @return LY_ERR values.
735 */
736static LY_ERR
737yin_parse_simple_elem(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
738 struct yin_subelement *subinfo, enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
739{
740 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
741 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subinfo->dest,
742 arg_type, arg_val_type, exts));
743 } else {
744 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subinfo->dest,
745 arg_type, arg_val_type, exts));
746 }
747
748 return LY_SUCCESS;
749}
750
751/**
752 * @brief Parse base element.
753 *
754 * @param[in,out] ctx YIN parser context for logging and to store current state.
755 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
756 * @param[in,out] data Data to read from, always moved to currently handled character.
757 * @param[in] parent Identification of parent element.
758 * @param[out] dest Where parsed values should be stored.
759 * @param[in,out] exts Extension instance to add to.
760 *
761 * @return LY_ERR values.
762 */
763static LY_ERR
764yin_parse_base(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword parent,
765 void *dest, struct lysp_ext_instance **exts)
766{
767 struct lysp_type *type = NULL;
768
769 if (parent == YANG_TYPE) {
770 type = (struct lysp_type *)dest;
771 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, YANG_BASE, &type->bases, YIN_ARG_NAME,
772 Y_PREF_IDENTIF_ARG, exts));
773 type->flags |= LYS_SET_BASE;
774 } else if (parent == YANG_IDENTITY) {
775 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, YANG_BASE, (const char ***)dest,
776 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
777 } else {
778 LOGINT(ctx->xml_ctx.ctx);
779 return LY_EINT;
780 }
781
782 return LY_SUCCESS;
783}
784
785/**
David Sedlákcf5569a2019-07-11 13:31:34 +0200786 * @brief Parse require instance element.
787 *
788 * @param[in,out] ctx Yin parser context for logging and to store current state.
789 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
790 * @param[in,out] data Data to read from, always moved to currently handled character.
791 * @prama[out] type Type structure to store value, flag and extensions.
792 *
793 * @return LY_ERR values.
794 */
795static LY_ERR
796yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
797 const char **data, struct lysp_type *type)
798{
799 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200800 struct yin_subelement subelems[1] = {
801 {YANG_CUSTOM, NULL, 0}
802 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200803
804 type->flags |= LYS_SET_REQINST;
805 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_REQUIRE_INSTANCE));
806 if (strcmp(temp_val, "true") == 0) {
807 type->require_instance = 1;
808 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák1538a842019-08-08 15:38:51 +0200809 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "require-instance");
David Sedlákcf5569a2019-07-11 13:31:34 +0200810 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
811 return LY_EVALID;
812 }
813 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
814
815 return yin_parse_content(ctx, subelems, 1, data, YANG_REQUIRE_INSTANCE, NULL, &type->exts);
816}
817
818/**
David Sedlákce77bf52019-07-11 16:59:31 +0200819 * @brief Parse modifier element.
820 *
821 * @param[in,out] ctx Yin parser context for logging and to store current state.
822 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
823 * @param[in,out] data Data to read from, always moved to currently handled character.
824 * @param[in,out] pat Value to write to.
825 * @param[in,out] exts Extension instances to add to.
826 *
827 * @return LY_ERR values.
828 */
829static LY_ERR
830yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
831 const char **pat, struct lysp_ext_instance **exts)
832{
David Sedlákd3983112019-07-12 11:20:56 +0200833 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200834 const char *temp_val;
835 char *modified_val;
836 struct yin_subelement subelems[1] = {
837 {YANG_CUSTOM, NULL, 0}
838 };
839
840 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MODIFIER));
841 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák1538a842019-08-08 15:38:51 +0200842 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "modifier");
David Sedlákce77bf52019-07-11 16:59:31 +0200843 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
844 return LY_EVALID;
845 }
David Sedlákd3983112019-07-12 11:20:56 +0200846 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200847
848 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200849 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200850 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200851 strcpy(modified_val, *pat);
852 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200853
854 /* modify the new value */
855 modified_val[0] = 0x15;
856 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
857
858 return yin_parse_content(ctx, subelems, 1, data, YANG_MODIFIER, NULL, exts);
859}
860
861/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200862 * @brief Parse a restriction element (length, range or one instance of must).
863 *
864 * @param[in,out] ctx Yin parser context for logging and to store current state.
865 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
866 * @param[in,out] data Data to read from, always moved to currently handled character.
867 * @param[in] restr_kw Identificaton of element that is being parsed, can be set to YANG_MUST, YANG_LENGTH or YANG_RANGE.
David Sedlák6542aed2019-08-14 10:47:43 +0200868 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200869 */
870static LY_ERR
871yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
872 enum yang_keyword restr_kw, struct lysp_restr *restr)
873{
874 assert(restr_kw == YANG_MUST || restr_kw == YANG_LENGTH || restr_kw == YANG_RANGE);
875 struct yin_subelement subelems[5] = {
David Sedlák968ac342019-07-11 15:17:59 +0200876 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
877 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
878 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
879 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
880 {YANG_CUSTOM, NULL, 0}
881 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200882 /* argument of must is called condition, but argument of length and range is called value */
David Sedlákc5b20842019-08-13 10:18:31 +0200883 enum yin_argument arg_type = (restr_kw == YANG_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200884 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
885
886 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
887}
888
889/**
David Sedlák6542aed2019-08-14 10:47:43 +0200890 * @brief Parse range element.
891 *
892 * @param[in,out] ctx Yin parser context for logging and to store current state.
893 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
894 * @param[in,out] data Data to read from, always moved to currently handled character.
895 * @param[out] type Type structure to store parsed value and flags.
896 *
897 * @return LY_ERR values.
898 */
899static LY_ERR
900yin_parse_range(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
901 const char **data, struct lysp_type *type)
902{
903 type->range = calloc(1, sizeof *type->range);
904 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
905 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, YANG_RANGE, type->range));
906 type->flags |= LYS_SET_RANGE;
907
908 return LY_SUCCESS;
909}
910
911/**
912 * @brief Parse length element.
913 *
914 * @param[in,out] ctx Yin parser context for logging and to store current state.
915 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
916 * @param[in,out] data Data to read from, always moved to currently handled character.
917 * @param[out] type Type structure to store parsed value and flags.
918 *
919 * @return LY_ERR values.
920 */
921static LY_ERR
922yin_parse_length(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
923 const char **data, struct lysp_type *type)
924{
925 type->length = calloc(1, sizeof *type->length);
926 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
927 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, YANG_LENGTH, type->length));
928 type->flags |= LYS_SET_LENGTH;
929
930 return LY_SUCCESS;
931}
932
933/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200934 * @brief Parse must element.
935 *
936 * @param[in,out] ctx YIN parser context for logging and to store current state.
937 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
938 * @param[in,out] data Data to read from, always moved to currently handled character.
939 * @param[in,out] restrs Restrictions to add to.
940 *
941 * @return LY_ERR values.
942 */
943static LY_ERR
944yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
945{
946 struct lysp_restr *restr;
947
948 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
949 return yin_parse_restriction(ctx, attrs, data, YANG_MUST, restr);
950}
951
952/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200953 * @brief Parse position or value element.
954 *
955 * @param[in,out] ctx YIN parser context for logging and to store current state.
956 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
957 * @param[in,out] data Data to read from, always moved to currently handled character.
958 * @param[in] kw Type of current element, can be set to YANG_POSITION or YANG_VALUE.
959 * @param[out] enm Enum structure to save value, flags and extensions.
960 *
961 * @return LY_ERR values.
962 */
963static LY_ERR
964yin_parse_value_pos_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
965 enum yang_keyword kw, struct lysp_type_enum *enm)
966{
967 assert(kw == YANG_POSITION || kw == YANG_VALUE);
968 const char *temp_val = NULL;
969 char *ptr;
970 long int num;
971 unsigned long int unum;
972
973 /* set value flag */
974 enm->flags |= LYS_SET_VALUE;
975
976 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200977 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 +0200978 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
979 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == YANG_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200980 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 +0200981 goto error;
982 }
983
984 /* convert value */
985 errno = 0;
986 if (kw == YANG_VALUE) {
987 num = strtol(temp_val, &ptr, 10);
988 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200989 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 +0200990 goto error;
991 }
992 } else {
993 unum = strtoul(temp_val, &ptr, 10);
994 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200995 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 +0200996 goto error;
997 }
998 }
999 /* check if whole argument value was converted */
1000 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001001 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 +02001002 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +02001003 }
1004 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +02001005 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 +02001006 goto error;
1007 }
1008 /* save correctly ternary operator can't be used because num and unum have different signes */
1009 if (kw == YANG_VALUE) {
1010 enm->value = num;
1011 } else {
1012 enm->value = unum;
1013 }
1014 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1015
1016 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +02001017 struct yin_subelement subelems[1] = {
1018 {YANG_CUSTOM, NULL, 0}
1019 };
David Sedlák5545f5d2019-07-11 11:55:16 +02001020 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
1021
1022 error:
1023 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1024 return LY_EVALID;
1025}
1026
David Sedlák05404f62019-07-24 14:11:53 +02001027
1028/**
1029 * @brief Parse belongs-to element.
1030 *
1031 * @param[in] ctx Yin parser context for logging and to store current state.
1032 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1033 * @param[in,out] data Data to read from, always moved to currently handled character.
1034 * @param[out] submod Structure of submodule that is being parsed.
1035 * @param[in,out] exts Extension instances to add to.
1036 *
1037 * @return LY_ERR values
1038 */
1039static LY_ERR
1040yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1041 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
1042{
1043 struct yin_subelement subelems[2] = {
1044 {YANG_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1045 {YANG_CUSTOM, NULL, 0}
1046 };
1047 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, YANG_BELONGS_TO));
1048
1049 return yin_parse_content(ctx, subelems, 2, data, YANG_BELONGS_TO, NULL, exts);
1050}
1051
David Sedlák5545f5d2019-07-11 11:55:16 +02001052/**
David Sedlákc1771b12019-07-10 15:55:46 +02001053 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákb4e44562019-07-04 15:42:12 +02001054 * text element as child
1055 *
David Sedlákda8ffa32019-07-08 14:17:10 +02001056 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001057 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákcf5569a2019-07-11 13:31:34 +02001058 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákc1771b12019-07-10 15:55:46 +02001059 * @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 +02001060 * @param[out] value Where the content of meta element should be stored.
David Sedlákbba38e52019-07-09 15:20:01 +02001061 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001062 *
1063 * @return LY_ERR values.
1064 */
1065static LY_ERR
David Sedlákdf2a9732019-08-07 13:23:16 +02001066yin_parse_meta_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1067 enum yang_keyword elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +02001068{
1069 assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
1070
David Sedlák968ac342019-07-11 15:17:59 +02001071 struct yin_subelement subelems[2] = {
1072 {YANG_CUSTOM, NULL, 0},
1073 {YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1074 };
David Sedlákdf2a9732019-08-07 13:23:16 +02001075 /* check attributes */
1076 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 +02001077
David Sedlákdf2a9732019-08-07 13:23:16 +02001078 /* parse content */
David Sedlákda8ffa32019-07-08 14:17:10 +02001079 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001080}
1081
1082/**
David Sedlákc1771b12019-07-10 15:55:46 +02001083 * @brief Parse error-message element.
1084 *
1085 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001086 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákc1771b12019-07-10 15:55:46 +02001087 * @param[in,out] data Data to read from.
1088 * @param[out] value Where the content of error-message element should be stored.
1089 * @param[in,out] exts Extension instance to add to.
1090 *
1091 * @return LY_ERR values.
1092 */
1093static LY_ERR
David Sedlákdf2a9732019-08-07 13:23:16 +02001094yin_parse_err_msg_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1095 const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +02001096{
David Sedlák968ac342019-07-11 15:17:59 +02001097 struct yin_subelement subelems[2] = {
1098 {YANG_CUSTOM, NULL, 0},
1099 {YIN_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1100 };
David Sedlákc1771b12019-07-10 15:55:46 +02001101
David Sedlákdf2a9732019-08-07 13:23:16 +02001102 /* check attributes */
1103 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, YANG_ERROR_MESSAGE));
1104
David Sedlákc1771b12019-07-10 15:55:46 +02001105 return yin_parse_content(ctx, subelems, 2, data, YANG_ERROR_MESSAGE, NULL, exts);
1106}
1107
1108/**
David Sedlák374d2b32019-07-17 15:06:55 +02001109 * @brief parse type element.
1110 *
David Sedlák6542aed2019-08-14 10:47:43 +02001111 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001112 *
1113 * @param[in,out] ctx YIN parser context for logging and to store current state.
1114 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1115 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák6542aed2019-08-14 10:47:43 +02001116 * @param[in] parent Identification of parent element.
David Sedlák374d2b32019-07-17 15:06:55 +02001117 * @param[in,out] type Type to wrote to.
David Sedlák374d2b32019-07-17 15:06:55 +02001118 *
1119 * @return LY_ERR values.
1120 */
1121static LY_ERR
David Sedlák6542aed2019-08-14 10:47:43 +02001122yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1123 enum yang_keyword parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001124{
David Sedlák6542aed2019-08-14 10:47:43 +02001125 struct lysp_type *type = NULL;
1126 if (parent == YANG_DEVIATE) {
1127 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
1128 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1129 type = *((struct lysp_type **)subinfo->dest);
1130 } else {
1131 type = (struct lysp_type *)subinfo->dest;
1132 }
1133 /* type as child of another type */
1134 if (parent == YANG_TYPE) {
1135 struct lysp_type *nested_type = NULL;
1136 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->types, nested_type, LY_EMEM);
1137 type->flags |= LYS_SET_TYPE;
1138 type = nested_type;
1139 }
David Sedlák374d2b32019-07-17 15:06:55 +02001140 struct yin_subelement subelems[11] = {
1141 {YANG_BASE, type, 0},
1142 {YANG_BIT, type, 0},
1143 {YANG_ENUM, type, 0},
1144 {YANG_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1145 {YANG_LENGTH, type, YIN_SUBELEM_UNIQUE},
1146 {YANG_PATH, type, YIN_SUBELEM_UNIQUE},
1147 {YANG_PATTERN, type, 0},
1148 {YANG_RANGE, type, YIN_SUBELEM_UNIQUE},
1149 {YANG_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1150 {YANG_TYPE, type},
1151 {YANG_CUSTOM, NULL, 0},
1152 };
1153 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, YANG_TYPE));
1154 return yin_parse_content(ctx, subelems, 11, data, YANG_TYPE, NULL, &type->exts);
1155}
1156
David Sedlák1af868e2019-07-17 17:03:14 +02001157/**
1158 * @brief Parse max-elements element.
1159 *
1160 * @param[in,out] ctx YIN parser context for logging and to store current state.
1161 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1162 * @param[in,out] data Data to read from, always moved to currently handled character.
1163 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001164 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001165 * @param[in,out] exts Extension instances to add to.
1166 *
1167 * @return LY_ERR values.
1168 */
1169static LY_ERR
1170yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
1171 uint16_t *flags, struct lysp_ext_instance **exts)
1172{
1173 const char *temp_val = NULL;
1174 char *ptr;
1175 unsigned long int num;
1176 struct yin_subelement subelems[1] = {
1177 {YANG_CUSTOM, NULL, 0},
1178 };
David Sedlák374d2b32019-07-17 15:06:55 +02001179
David Sedlák1af868e2019-07-17 17:03:14 +02001180 *flags |= LYS_SET_MAX;
1181 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MAX_ELEMENTS));
1182 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 +02001183 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001184 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1185 return LY_EVALID;
1186 }
1187
1188 if (strcmp(temp_val, "unbounded")) {
1189 errno = 0;
1190 num = strtoul(temp_val, &ptr, 10);
1191 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001192 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001193 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1194 return LY_EVALID;
1195 }
1196 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001197 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001198 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1199 return LY_EVALID;
1200 }
1201 *max = num;
1202 }
1203 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1204 return yin_parse_content(ctx, subelems, 1, data, YANG_MAX_ELEMENTS, NULL, exts);
1205}
David Sedlák374d2b32019-07-17 15:06:55 +02001206
1207/**
David Sedlák09e18c92019-07-18 11:17:11 +02001208 * @brief Parse max-elements element.
1209 *
1210 * @param[in,out] ctx YIN parser context for logging and to store current state.
1211 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1212 * @param[in,out] data Data to read from, always moved to currently handled character.
1213 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001214 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001215 * @param[in,out] exts Extension instances to add to.
1216 *
1217 * @return LY_ERR values.
1218 */
1219static LY_ERR
1220yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
1221 uint16_t *flags, struct lysp_ext_instance **exts)
1222{
1223 const char *temp_val = NULL;
1224 char *ptr;
1225 unsigned long int num;
1226 struct yin_subelement subelems[1] = {
1227 {YANG_CUSTOM, NULL, 0},
1228 };
1229
1230 *flags |= LYS_SET_MIN;
David Sedláka2dad212019-07-18 12:45:19 +02001231 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 +02001232
1233 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001234 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001235 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1236 return LY_EVALID;
1237 }
1238
1239 errno = 0;
1240 num = strtoul(temp_val, &ptr, 10);
1241 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001242 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001243 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1244 return LY_EVALID;
1245 }
1246 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001247 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001248 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1249 return LY_EVALID;
1250 }
1251 *min = num;
1252 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001253 return yin_parse_content(ctx, subelems, 1, data, YANG_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001254}
1255
David Sedláka2dad212019-07-18 12:45:19 +02001256/**
1257 * @brief Parse min-elements or max-elements element.
1258 *
1259 * @param[in,out] ctx YIN parser context for logging and to store current state.
1260 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1261 * @param[in,out] data Data to read from, always moved to currently handled character.
1262 * @param[in] parent Identification of parent element.
1263 * @param[in] current Identification of current element.
1264 * @param[in] dest Where the parsed value and flags should be stored.
1265 *
1266 * @return LY_ERR values.
1267 */
David Sedlák09e18c92019-07-18 11:17:11 +02001268static LY_ERR
1269yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1270 enum yang_keyword parent, enum yang_keyword current, void *dest)
1271{
1272 assert(current == YANG_MAX_ELEMENTS || current == YANG_MIN_ELEMENTS);
David Sedlák4ffcec82019-07-25 15:10:21 +02001273 assert(parent == YANG_LEAF_LIST || parent == YANG_REFINE || parent == YANG_LIST || parent == YANG_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001274 uint32_t *lim;
1275 uint16_t *flags;
1276 struct lysp_ext_instance **exts;
1277
1278 if (parent == YANG_LEAF_LIST) {
1279 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
1280 flags = &((struct lysp_node_leaflist *)dest)->flags;
1281 exts = &((struct lysp_node_leaflist *)dest)->exts;
1282 } else if (parent == YANG_REFINE) {
1283 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
1284 flags = &((struct lysp_refine *)dest)->flags;
1285 exts = &((struct lysp_refine *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001286 } else if (parent == YANG_LIST) {
David Sedlák09e18c92019-07-18 11:17:11 +02001287 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
1288 flags = &((struct lysp_node_list *)dest)->flags;
1289 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001290 } else {
1291 lim = ((struct minmax_dev_meta *)dest)->lim;
1292 flags = ((struct minmax_dev_meta *)dest)->flags;
1293 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001294 }
1295
1296 if (current == YANG_MAX_ELEMENTS) {
1297 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1298 } else {
1299 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1300 }
1301
1302 return LY_SUCCESS;
1303}
1304
1305/**
David Sedláka2dad212019-07-18 12:45:19 +02001306 * @brief Parser ordered-by element.
1307 *
1308 * @param[in,out] ctx YIN parser context for logging and to store current state.
1309 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1310 * @param[in,out] data Data to read from, always moved to currently handled character.
1311 * @param[out] flags Flags to write to.
1312 * @param[in,out] exts Extension instance to add to.
1313 *
1314 * @return LY_ERR values.
1315 */
1316static LY_ERR
1317yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1318 uint16_t *flags, struct lysp_ext_instance **exts)
1319{
1320 const char *temp_val;
1321 struct yin_subelement subelems[1] = {
1322 {YANG_CUSTOM, NULL, 0},
1323 };
1324
1325 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_ORDERED_BY));
1326 if (strcmp(temp_val, "system") == 0) {
1327 *flags |= LYS_ORDBY_SYSTEM;
1328 } else if (strcmp(temp_val, "user") == 0) {
1329 *flags |= LYS_ORDBY_USER;
1330 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001331 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "ordered-by");
David Sedláka2dad212019-07-18 12:45:19 +02001332 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1333 return LY_EVALID;
1334 }
1335 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1336
1337 return yin_parse_content(ctx, subelems, 1, data, YANG_ORDERED_BY, NULL, exts);
1338}
1339
1340/**
David Sedlák8a83bbb2019-07-18 14:46:00 +02001341 * @brief parse any-data or any-xml element.
1342 *
1343 * @param[in,out] ctx YIN parser context for logging and to store current state.
1344 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1345 * @param[in,out] data Data to read from, always moved to currently handled character.
1346 * @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 +02001347 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001348 *
1349 * @return LY_ERR values.
1350 */
1351static LY_ERR
1352yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1353 enum yang_keyword any_kw, struct tree_node_meta *node_meta)
1354{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001355 struct lysp_node_anydata *any;
1356
David Sedlák8d552d62019-08-06 15:29:05 +02001357 /* create new sibling */
1358 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, any, next);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001359 any->nodetype = (any_kw == YANG_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
1360 any->parent = node_meta->parent;
1361
David Sedlák8a83bbb2019-07-18 14:46:00 +02001362 /* parser argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001363 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 +02001364
1365 struct yin_subelement subelems[9] = {
1366 {YANG_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1367 {YANG_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1368 {YANG_IF_FEATURE, &any->iffeatures, 0},
1369 {YANG_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1370 {YANG_MUST, &any->musts, 0},
1371 {YANG_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1372 {YANG_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1373 {YANG_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1374 {YANG_CUSTOM, NULL, 0},
1375 };
1376 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1377}
1378
1379/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001380 * @brief parse leaf element.
1381 *
1382 * @param[in,out] ctx YIN parser context for logging and to store current state.
1383 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1384 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001385 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001386 *
1387 * @return LY_ERR values.
1388 */
1389static LY_ERR
1390yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1391 struct tree_node_meta *node_meta)
1392{
David Sedlák203ca3a2019-07-18 15:26:25 +02001393 struct lysp_node_leaf *leaf;
1394
David Sedlák8d552d62019-08-06 15:29:05 +02001395 /* create structure new leaf */
1396 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, leaf, next);
David Sedlák203ca3a2019-07-18 15:26:25 +02001397 leaf->nodetype = LYS_LEAF;
1398 leaf->parent = node_meta->parent;
1399
David Sedlák203ca3a2019-07-18 15:26:25 +02001400 /* parser argument */
1401 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, YANG_LEAF));
1402
1403 /* parse content */
1404 struct yin_subelement subelems[12] = {
1405 {YANG_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1406 {YANG_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1407 {YANG_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1408 {YANG_IF_FEATURE, &leaf->iffeatures, 0},
1409 {YANG_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1410 {YANG_MUST, &leaf->musts, 0},
1411 {YANG_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1412 {YANG_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1413 {YANG_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1414 {YANG_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1415 {YANG_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1416 {YANG_CUSTOM, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001417 };
David Sedlák203ca3a2019-07-18 15:26:25 +02001418 return yin_parse_content(ctx, subelems, 12, data, YANG_LEAF, NULL, &leaf->exts);
1419}
1420
1421/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001422 * @brief Parse leaf-list element.
1423 *
1424 * @param[in,out] ctx YIN parser context for logging and to store current state.
1425 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1426 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001427 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001428 *
1429 * @return LY_ERR values.
1430 */
1431static LY_ERR
1432yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1433 struct tree_node_meta *node_meta)
1434{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001435 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001436
David Sedlák8d552d62019-08-06 15:29:05 +02001437 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, llist, next);
1438
David Sedlákc3da3ef2019-07-19 12:56:08 +02001439 llist->nodetype = LYS_LEAFLIST;
1440 llist->parent = node_meta->parent;
1441
David Sedlákc3da3ef2019-07-19 12:56:08 +02001442 /* parse argument */
1443 yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, YANG_LEAF_LIST);
1444
1445 /* parse content */
1446 struct yin_subelement subelems[14] = {
1447 {YANG_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1448 {YANG_DEFAULT, &llist->dflts, 0},
1449 {YANG_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1450 {YANG_IF_FEATURE, &llist->iffeatures, 0},
1451 {YANG_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1452 {YANG_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1453 {YANG_MUST, &llist->musts, 0},
1454 {YANG_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1455 {YANG_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1456 {YANG_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1457 {YANG_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1458 {YANG_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1459 {YANG_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1460 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001461 };
David Sedlákc3da3ef2019-07-19 12:56:08 +02001462 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, YANG_LEAF_LIST, NULL, &llist->exts));
1463
1464 /* invalid combination of subelements */
1465 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001466 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001467 return LY_EVALID;
1468 }
1469 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001470 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001471 return LY_EVALID;
1472 }
1473
1474 return LY_SUCCESS;
1475}
1476
1477/**
David Sedlák04e17b22019-07-19 15:29:48 +02001478 * @brief Parse typedef element.
1479 *
1480 * @param[in,out] ctx YIN parser context for logging and to store current state.
1481 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1482 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001483 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001484 *
1485 * @return LY_ERR values.
1486 */
1487static LY_ERR
1488yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02001489 struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001490{
1491 struct lysp_tpdf *tpdf;
David Sedlák6881b512019-08-13 12:52:00 +02001492 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->siblings;
1493 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001494
1495 /* parse argument */
1496 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, YANG_TYPEDEF));
1497
1498 /* parse content */
1499 struct yin_subelement subelems[7] = {
1500 {YANG_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1501 {YANG_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1502 {YANG_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1503 {YANG_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1504 {YANG_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1505 {YANG_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1506 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001507 };
David Sedlák04e17b22019-07-19 15:29:48 +02001508 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, YANG_TYPEDEF, NULL, &tpdf->exts));
1509
1510 /* store data for collision check */
1511 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
1512 ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0);
1513 }
1514
1515 return LY_SUCCESS;
1516}
1517
1518/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001519 * @brief Parse refine element.
1520 *
1521 * @param[in,out] ctx YIN parser context for logging and to store current state.
1522 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1523 * @param[in,out] data Data to read from, always moved to currently handled character.
1524 * @param[in,out] refines Refines to add to.
1525 *
1526 * @return LY_ERR values.
1527 */
1528static LY_ERR
1529yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1530 struct lysp_refine **refines)
1531{
1532 struct lysp_refine *rf;
1533
1534 /* allocate new refine */
1535 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1536
1537 /* parse attribute */
1538 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, YANG_REFINE));
1539 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1540
1541 /* parse content */
1542 struct yin_subelement subelems[11] = {
1543 {YANG_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1544 {YANG_DEFAULT, &rf->dflts, 0},
1545 {YANG_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1546 {YANG_IF_FEATURE, &rf->iffeatures, 0},
1547 {YANG_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1548 {YANG_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1549 {YANG_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1550 {YANG_MUST, &rf->musts, 0},
1551 {YANG_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1552 {YANG_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1553 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001554 };
David Sedlákd2d676a2019-07-22 11:28:19 +02001555 return yin_parse_content(ctx, subelems, 11, data, YANG_REFINE, NULL, &rf->exts);
1556}
1557
1558/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001559 * @brief Parse uses element.
1560 *
1561 * @param[in,out] ctx YIN parser context for logging and to store current state.
1562 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1563 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001564 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001565 *
1566 * @return LY_ERR values.
1567 */
1568static LY_ERR
1569yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1570 struct tree_node_meta *node_meta)
1571{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001572 struct lysp_node_uses *uses;
1573
David Sedlák8d552d62019-08-06 15:29:05 +02001574 /* create new uses */
1575 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, uses, next);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001576 uses->nodetype = LYS_USES;
1577 uses->parent = node_meta->parent;
1578
David Sedlák0d6de5a2019-07-22 13:25:44 +02001579 /* parse argument */
1580 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, YANG_USES));
1581
1582 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001583 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001584 struct yin_subelement subelems[8] = {
1585 {YANG_AUGMENT, &augments, 0},
1586 {YANG_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1587 {YANG_IF_FEATURE, &uses->iffeatures, 0},
1588 {YANG_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1589 {YANG_REFINE, &uses->refines, 0},
1590 {YANG_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1591 {YANG_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1592 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001593 };
David Sedlák0d6de5a2019-07-22 13:25:44 +02001594 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, YANG_USES, NULL, &uses->exts));
1595 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1596
1597 return LY_SUCCESS;
1598}
1599
1600/**
David Sedlákaa854b02019-07-22 14:17:10 +02001601 * @brief Parse revision element.
1602 *
1603 * @param[in,out] ctx YIN parser context for logging and to store current state.
1604 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1605 * @param[in,out] data Data to read from, always moved to currently handled character.
1606 * @param[in,out] revs Parsed revisions to add to.
1607 *
1608 * @return LY_ERR values.
1609 */
1610static LY_ERR
1611yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1612 struct lysp_revision **revs)
1613{
1614 struct lysp_revision *rev;
1615 const char *temp_date = NULL;
1616
1617 /* allocate new reivison */
1618 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1619
1620 /* parse argument */
1621 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, YANG_REVISION));
1622 /* check value */
1623 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1624 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1625 return LY_EVALID;
1626 }
1627 strcpy(rev->date, temp_date);
1628 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1629
1630 /* parse content */
1631 struct yin_subelement subelems[3] = {
1632 {YANG_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1633 {YANG_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1634 {YANG_CUSTOM, NULL, 0},
1635 };
1636 return yin_parse_content(ctx, subelems, 3, data, YANG_REVISION, NULL, &rev->exts);
1637}
1638
David Sedlák5e13dea2019-07-22 16:06:45 +02001639/**
1640 * @brief Parse include element.
1641 *
1642 * @param[in,out] ctx YIN parser context for logging and to store current state.
1643 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1644 * @param[in,out] data Data to read from, always moved to currently handled character.
1645 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1646 *
1647 * @return LY_ERR values.
1648 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001649static LY_ERR
1650yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1651 struct include_meta *inc_meta)
1652{
1653 struct lysp_include *inc;
1654
1655 /* allocate new include */
1656 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1657
1658 /* parse argument */
1659 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, YANG_INCLUDE));
1660
1661 /* submodules share the namespace with the module names, so there must not be
1662 * a module of the same name in the context, no need for revision matching */
1663 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 +02001664 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001665 return LY_EVALID;
1666 }
1667
1668 /* parse content */
1669 struct yin_subelement subelems[4] = {
1670 {YANG_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1671 {YANG_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1672 {YANG_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1673 {YANG_CUSTOM, NULL, 0},
1674 };
1675 return yin_parse_content(ctx, subelems, 4, data, YANG_INCLUDE, NULL, &inc->exts);
1676}
1677
David Sedlákaa854b02019-07-22 14:17:10 +02001678/**
David Sedlákdfbbb442019-08-06 16:33:21 +02001679 * @brief Parse revision date element.
1680 *
1681 * @param[in,out] ctx Yin parser context for logging and to store current state.
1682 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of revision-date element.
1683 * @param[in,out] data Data to read from, always moved to currently handled character.
1684 * @param[in,out] rev Array to store the parsed value in.
1685 * @param[in,out] exts Extension instances to add to.
1686 *
1687 * @return LY_ERR values.
1688 */
1689static LY_ERR
1690yin_parse_revision_date(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, char *rev,
1691 struct lysp_ext_instance **exts)
1692{
1693 const char *temp_rev;
1694 struct yin_subelement subelems[1] = {
1695 {YANG_CUSTOM, NULL, 0}
1696 };
1697
1698 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, YANG_REVISION_DATE));
1699 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
1700 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
1701
1702 strcpy(rev, temp_rev);
1703 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
1704
1705 return yin_parse_content(ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
1706}
1707
1708/**
1709 * @brief Parse config element.
1710 *
1711 * @param[in] ctx Yin parser context for logging and to store current state.
1712 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1713 * @param[in,out] data Data to read from, always moved to currently handled character.
1714 * @param[in,out] flags Flags to add to.
1715 * @param[in,out] exts Extension instances to add to.
1716 *
1717 * @return LY_ERR values.
1718 */
1719static LY_ERR
1720yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1721 struct lysp_ext_instance **exts)
1722{
1723 const char *temp_val = NULL;
1724 struct yin_subelement subelems[1] = {
1725 {YANG_CUSTOM, NULL, 0}
1726 };
1727
1728 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_CONFIG));
1729 if (strcmp(temp_val, "true") == 0) {
1730 *flags |= LYS_CONFIG_W;
1731 } else if (strcmp(temp_val, "false") == 0) {
1732 *flags |= LYS_CONFIG_R;
1733 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001734 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "config");
David Sedlákdfbbb442019-08-06 16:33:21 +02001735 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1736 return LY_EVALID;
1737 }
1738 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1739
1740 return yin_parse_content(ctx, subelems, 1, data, YANG_CONFIG, NULL, exts);
1741}
1742
1743/**
1744 * @brief Parse yang-version element.
1745 *
1746 * @param[in,out] ctx Yin parser context for logging and to store current state.
1747 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yang-version element.
1748 * @param[in] data Data to read from, always moved to currently handled character.
1749 * @param[out] version Storage for the parsed information.
1750 * @param[in,out] exts Extension instance to add to.
1751 *
1752 * @return LY_ERR values.
1753 */
1754static LY_ERR
1755yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
1756 struct lysp_ext_instance **exts)
1757{
1758 const char *temp_version = NULL;
1759 struct yin_subelement subelems[1] = {
1760 {YANG_CUSTOM, NULL, 0}
1761 };
1762
1763 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, YANG_YANG_VERSION));
1764 if (strcmp(temp_version, "1.0") == 0) {
1765 *version = LYS_VERSION_1_0;
1766 } else if (strcmp(temp_version, "1.1") == 0) {
1767 *version = LYS_VERSION_1_1;
1768 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001769 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_version, "value", "yang-version");
David Sedlákdfbbb442019-08-06 16:33:21 +02001770 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1771 return LY_EVALID;
1772 }
1773 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1774 ctx->mod_version = *version;
1775
1776 return yin_parse_content(ctx, subelems, 1, data, YANG_YANG_VERSION, NULL, exts);
1777}
1778
1779/**
1780 * @brief Parse import element.
1781 *
1782 * @param[in,out] ctx Yin parser context for logging and to store current state.
1783 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1784 * @param[in,out] data Data to read from, always moved to currently handled character.
1785 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1786 *
1787 * @return LY_ERR values.
1788 */
1789static LY_ERR
1790yin_parse_import(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct import_meta *imp_meta)
1791{
1792 struct lysp_import *imp;
1793 /* allocate new element in sized array for import */
1794 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
1795
1796 struct yin_subelement subelems[5] = {
1797 {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1798 {YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1799 {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1800 {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1801 {YANG_CUSTOM, NULL, 0}
1802 };
1803
1804 /* parse import attributes */
1805 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, YANG_IMPORT));
1806 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
1807 /* check prefix validity */
1808 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1809
1810 return LY_SUCCESS;
1811}
1812
1813/**
1814 * @brief Parse mandatory element.
1815 *
1816 * @param[in,out] ctx Yin parser context for logging and to store current state.
1817 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1818 * @param[in,out] data Data to read from, always moved to currently handled character.
1819 * @param[in,out] flags Flags to add to.
1820 * @param[in,out] exts Extension instances to add to.
1821 *
1822 * @return LY_ERR values.
1823 */
1824static LY_ERR
1825yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1826 struct lysp_ext_instance **exts)
1827{
1828 const char *temp_val = NULL;
1829 struct yin_subelement subelems[1] = {
1830 {YANG_CUSTOM, NULL, 0}
1831 };
1832
1833 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MANDATORY));
1834 if (strcmp(temp_val, "true") == 0) {
1835 *flags |= LYS_MAND_TRUE;
1836 } else if (strcmp(temp_val, "false") == 0) {
1837 *flags |= LYS_MAND_FALSE;
1838 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001839 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "mandatory");
David Sedlákdfbbb442019-08-06 16:33:21 +02001840 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1841 return LY_EVALID;
1842 }
1843 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1844
1845 return yin_parse_content(ctx, subelems, 1, data, YANG_MANDATORY, NULL, exts);
1846}
1847
1848/**
1849 * @brief Parse status element.
1850 *
1851 * @param[in,out] ctx Yin parser context for logging and to store current state.
1852 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1853 * @param[in,out] data Data to read from, always moved to currently handled character.
1854 * @param[in,out] flags Flags to add to.
1855 * @param[in,out] exts Extension instances to add to.
1856 *
1857 * @return LY_ERR values.
1858 */
1859static LY_ERR
1860yin_parse_status(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1861 struct lysp_ext_instance **exts)
1862{
1863 const char *value = NULL;
1864 struct yin_subelement subelems[1] = {
1865 {YANG_CUSTOM, NULL, 0}
1866 };
1867
1868 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &value, Y_STR_ARG, YANG_STATUS));
1869 if (strcmp(value, "current") == 0) {
1870 *flags |= LYS_STATUS_CURR;
1871 } else if (strcmp(value, "deprecated") == 0) {
1872 *flags |= LYS_STATUS_DEPRC;
1873 } else if (strcmp(value, "obsolete") == 0) {
1874 *flags |= LYS_STATUS_OBSLT;
1875 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001876 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, value, "value", "status");
David Sedlákdfbbb442019-08-06 16:33:21 +02001877 FREE_STRING(ctx->xml_ctx.ctx, value);
1878 return LY_EVALID;
1879 }
1880 FREE_STRING(ctx->xml_ctx.ctx, value);
1881
1882 return yin_parse_content(ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
1883}
1884
1885/**
1886 * @brief Parse when element.
1887 *
1888 * @param[in,out] ctx Yin parser context for logging and to store current state.
1889 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of when element.
1890 * @param[in,out] data Data to read from, always moved to currently handled character.
1891 * @param[out] when_p When pointer to parse to.
1892 */
1893static LY_ERR
1894yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
1895{
1896 struct lysp_when *when;
1897 when = calloc(1, sizeof *when);
1898 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1899 yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, YANG_WHEN);
1900 *when_p = when;
1901 struct yin_subelement subelems[3] = {
1902 {YANG_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1903 {YANG_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1904 {YANG_CUSTOM, NULL, 0}
1905 };
1906
1907 return yin_parse_content(ctx, subelems, 3, data, YANG_WHEN, NULL, &when->exts);
1908}
1909
1910/**
1911 * @brief Parse yin-elemenet element.
1912 *
1913 * @param[in,out] ctx Yin parser context for logging and to store current state.
1914 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yin-element element.
1915 * @param[in,out] data Data to read from, always moved to currently handled position.
1916 * @param[in,out] flags Flags to add to.
1917 * @prama[in,out] exts Extension instance to add to.
1918 *
1919 * @return LY_ERR values.
1920 */
1921static LY_ERR
1922yin_parse_yin_element_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1923 uint16_t *flags, struct lysp_ext_instance **exts)
1924{
1925 const char *temp_val = NULL;
1926 struct yin_subelement subelems[1] = {
1927 {YANG_CUSTOM, NULL, 0}
1928 };
1929
1930 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_YIN_ELEMENT));
1931 if (strcmp(temp_val, "true") == 0) {
1932 *flags |= LYS_YINELEM_TRUE;
1933 } else if (strcmp(temp_val, "false") == 0) {
1934 *flags |= LYS_YINELEM_FALSE;
1935 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001936 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "yin-element");
David Sedlákdfbbb442019-08-06 16:33:21 +02001937 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1938 return LY_EVALID;
1939 }
1940 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1941
1942 return yin_parse_content(ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
1943}
1944
1945/**
1946 * @brief Parse argument element.
1947 *
1948 * @param[in,out] xml_ctx Xml context.
1949 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of argument element.
1950 * @param[in,out] data Data to read from, always moved to currently handled character.
1951 * @param[in,out] arg_meta Meta information about destionation af prased data.
1952 * @param[in,out] exts Extension instance to add to.
1953 *
1954 * @return LY_ERR values.
1955 */
1956static LY_ERR
1957yin_parse_argument_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1958 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
1959{
1960 struct yin_subelement subelems[2] = {
1961 {YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1962 {YANG_CUSTOM, NULL, 0}
1963 };
1964
1965 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, YANG_ARGUMENT));
1966
1967 return yin_parse_content(ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
1968}
1969
1970/**
1971 * @brief Parse the extension statement.
1972 *
1973 * @param[in,out] ctx Yin parser context for logging and to store current state.
1974 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension element.
1975 * @param[in,out] data Data to read from.
1976 * @param[in,out] extensions Extensions to add to.
1977 *
1978 * @return LY_ERR values.
1979 */
1980static LY_ERR
1981yin_parse_extension(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_ext **extensions)
1982{
1983 struct lysp_ext *ex;
1984 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
1985 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ex->name, Y_IDENTIF_ARG, YANG_EXTENSION));
1986
1987 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1988 struct yin_subelement subelems[5] = {
1989 {YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1990 {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1991 {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1992 {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1993 {YANG_CUSTOM, NULL, 0}
1994 };
1995
1996 return yin_parse_content(ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
1997}
1998
1999/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002000 * @brief Parse feature element.
2001 *
2002 * @param[in,out] ctx YIN parser context for logging and to store current state.
2003 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2004 * @param[in,out] data Data to read from, always moved to currently handled character.
2005 * @param[in,out] features Features to add to.
2006 *
2007 * @return LY_ERR values.
2008 */
2009static LY_ERR
2010yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2011 struct lysp_feature **features)
2012{
2013 struct lysp_feature *feat;
2014
2015 /* allocate new feature */
2016 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
2017
2018 /* parse argument */
2019 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, YANG_FEATURE));
2020
2021 /* parse content */
2022 struct yin_subelement subelems[5] = {
2023 {YANG_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2024 {YANG_IF_FEATURE, &feat->iffeatures, 0},
2025 {YANG_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2026 {YANG_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2027 {YANG_CUSTOM, NULL, 0},
2028 };
2029 return yin_parse_content(ctx, subelems, 5, data, YANG_FEATURE, NULL, &feat->exts);
2030}
2031
2032/**
David Sedlák28794f22019-07-22 16:45:00 +02002033 * @brief Parse identity element.
2034 *
2035 * @param[in,out] ctx YIN parser context for logging and to store current state.
2036 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2037 * @param[in,out] data Data to read from, always moved to currently handled character.
2038 * @param[in,out] identities Identities to add to.
2039 *
2040 * @return LY_ERR values.
2041 */
2042static LY_ERR
2043yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2044 struct lysp_ident **identities)
2045{
2046 struct lysp_ident *ident;
2047
2048 /* allocate new identity */
2049 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
2050
2051 /* parse argument */
2052 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, YANG_IDENTITY));
2053
2054 /* parse content */
2055 struct yin_subelement subelems[6] = {
2056 {YANG_BASE, &ident->bases, 0},
2057 {YANG_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2058 {YANG_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2059 {YANG_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2060 {YANG_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2061 {YANG_CUSTOM, NULL, 0},
2062 };
2063 return yin_parse_content(ctx, subelems, 6, data, YANG_IDENTITY, NULL, &ident->exts);
2064}
2065
2066/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002067 * @brief Parse list element.
2068 *
2069 * @param[in,out] ctx YIN parser context for logging and to store current state.
2070 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2071 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002072 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002073 *
2074 * @return LY_ERR values.
2075 */
2076static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02002077yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2078 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002079{
David Sedlákaf536aa2019-07-23 13:42:23 +02002080 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002081 LY_ERR ret = LY_SUCCESS;
2082 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02002083
David Sedlák8d552d62019-08-06 15:29:05 +02002084 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, list, next);
David Sedlákaf536aa2019-07-23 13:42:23 +02002085 list->nodetype = LYS_LIST;
2086 list->parent = node_meta->parent;
2087
David Sedlákaf536aa2019-07-23 13:42:23 +02002088 /* parse argument */
2089 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, YANG_LIST));
2090
2091 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02002092 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
2093 YANG_ACTION, &list->actions, 0,
2094 YANG_ANYDATA, &list->child, 0,
2095 YANG_ANYXML, &list->child, 0,
2096 YANG_CHOICE, &list->child, 0,
2097 YANG_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2098 YANG_CONTAINER, &list->child, 0,
2099 YANG_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2100 YANG_GROUPING, &list->groupings, 0,
2101 YANG_IF_FEATURE, &list->iffeatures, 0,
2102 YANG_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2103 YANG_LEAF, &list->child, 0,
2104 YANG_LEAF_LIST, &list->child, 0,
2105 YANG_LIST, &list->child, 0,
2106 YANG_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2107 YANG_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2108 YANG_MUST, &list->musts, 0,
2109 YANG_NOTIFICATION, &list->notifs, 0,
2110 YANG_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2111 YANG_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2112 YANG_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2113 YANG_TYPEDEF, &list->typedefs, 0,
2114 YANG_UNIQUE, &list->uniques, 0,
2115 YANG_USES, &list->child, 0,
2116 YANG_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2117 YANG_CUSTOM, NULL, 0
2118 ));
2119 ret = yin_parse_content(ctx, subelems, 25, data, YANG_LIST, NULL, &list->exts);
2120 subelems_deallocator(25, subelems);
2121 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002122
2123 /* finalize parent pointers to the reallocated items */
2124 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
2125
2126 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02002127 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002128 return LY_EVALID;
2129 }
2130
2131 return LY_SUCCESS;
2132}
2133
2134/**
David Sedlák031b9e72019-07-23 15:19:37 +02002135 * @brief Parse notification element.
2136 *
2137 * @param[in,out] ctx YIN parser context for logging and to store current state.
2138 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2139 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02002140 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002141 *
2142 * @return LY_ERR values.
2143 */
2144static LY_ERR
2145yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002146 struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002147{
2148 struct lysp_notif *notif;
David Sedlák6881b512019-08-13 12:52:00 +02002149 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->siblings;
David Sedlák81497a32019-08-13 16:56:26 +02002150 LY_ERR ret = LY_SUCCESS;
2151 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002152
2153 /* allocate new notification */
David Sedlák6881b512019-08-13 12:52:00 +02002154 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002155 notif->nodetype = LYS_NOTIF;
2156 notif->parent = notif_meta->parent;
2157
2158 /* parse argument */
2159 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, YANG_NOTIFICATION));
2160
2161 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002162 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
2163 YANG_ANYDATA, &notif->data, 0,
2164 YANG_ANYXML, &notif->data, 0,
2165 YANG_CHOICE, &notif->data, 0,
2166 YANG_CONTAINER, &notif->data, 0,
2167 YANG_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2168 YANG_GROUPING, &notif->groupings, 0,
2169 YANG_IF_FEATURE, &notif->iffeatures, 0,
2170 YANG_LEAF, &notif->data, 0,
2171 YANG_LEAF_LIST, &notif->data, 0,
2172 YANG_LIST, &notif->data, 0,
2173 YANG_MUST, &notif->musts, YIN_SUBELEM_VER2,
2174 YANG_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2175 YANG_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2176 YANG_TYPEDEF, &notif->typedefs, 0,
2177 YANG_USES, &notif->data, 0,
2178 YANG_CUSTOM, NULL, 0
2179 ));
2180
2181 ret = yin_parse_content(ctx, subelems, 16, data, YANG_NOTIFICATION, NULL, &notif->exts);
2182 subelems_deallocator(16, subelems);
2183 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002184
2185 /* finalize parent pointers to the reallocated items */
2186 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2187
2188 return LY_SUCCESS;
2189}
2190
2191/**
David Sedláke3ce9ef2019-07-23 16:34:30 +02002192 * @brief Parse notification element.
2193 *
2194 * @param[in,out] ctx YIN parser context for logging and to store current state.
2195 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2196 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02002197 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002198 *
2199 * @return LY_ERR values.
2200 */
2201static LY_ERR
2202yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002203 struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002204{
2205 struct lysp_grp *grp;
David Sedlák6881b512019-08-13 12:52:00 +02002206 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->siblings;
David Sedlák81497a32019-08-13 16:56:26 +02002207 LY_ERR ret = LY_SUCCESS;
2208 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002209
2210 /* create new grouping */
David Sedlák6881b512019-08-13 12:52:00 +02002211 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002212 grp->nodetype = LYS_GROUPING;
2213 grp->parent = gr_meta->parent;
2214
2215 /* parse argument */
2216 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, YANG_GROUPING));
2217
2218 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002219 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
2220 YANG_ACTION, &grp->actions, 0,
2221 YANG_ANYDATA, &grp->data, 0,
2222 YANG_ANYXML, &grp->data, 0,
2223 YANG_CHOICE, &grp->data, 0,
2224 YANG_CONTAINER, &grp->data, 0,
2225 YANG_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2226 YANG_GROUPING, &grp->groupings, 0,
2227 YANG_LEAF, &grp->data, 0,
2228 YANG_LEAF_LIST, &grp->data, 0,
2229 YANG_LIST, &grp->data, 0,
2230 YANG_NOTIFICATION, &grp->notifs, 0,
2231 YANG_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2232 YANG_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2233 YANG_TYPEDEF, &grp->typedefs, 0,
2234 YANG_USES, &grp->data, 0,
2235 YANG_CUSTOM, NULL, 0
2236 ));
2237 ret = yin_parse_content(ctx, subelems, 16, data, YANG_GROUPING, NULL, &grp->exts);
2238 subelems_deallocator(16, subelems);
2239 LY_CHECK_RET(ret);
2240
David Sedláke3ce9ef2019-07-23 16:34:30 +02002241 /* finalize parent pointers to the reallocated items */
2242 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2243
2244 return LY_SUCCESS;
2245}
2246
2247/**
David Sedlákf111bcb2019-07-23 17:15:51 +02002248 * @brief Parse list element.
2249 *
2250 * @param[in,out] ctx YIN parser context for logging and to store current state.
2251 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2252 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002253 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002254 *
2255 * @return LY_ERR values.
2256 */
2257static LY_ERR
2258yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2259 struct tree_node_meta *node_meta)
2260{
David Sedlákf111bcb2019-07-23 17:15:51 +02002261 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002262 LY_ERR ret = LY_SUCCESS;
2263 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002264
2265 /* create new container */
David Sedlák8d552d62019-08-06 15:29:05 +02002266 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, cont, next);
David Sedlákf111bcb2019-07-23 17:15:51 +02002267 cont->nodetype = LYS_CONTAINER;
2268 cont->parent = node_meta->parent;
2269
David Sedlákf111bcb2019-07-23 17:15:51 +02002270 /* parse aegument */
2271 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, YANG_CONTAINER));
2272
2273 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002274 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
2275 YANG_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2276 YANG_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2277 YANG_ANYXML, &cont->child, 0,
2278 YANG_CHOICE, &cont->child, 0,
2279 YANG_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2280 YANG_CONTAINER, &cont->child, 0,
2281 YANG_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2282 YANG_GROUPING, &cont->groupings, 0,
2283 YANG_IF_FEATURE, &cont->iffeatures, 0,
2284 YANG_LEAF, &cont->child, 0,
2285 YANG_LEAF_LIST, &cont->child, 0,
2286 YANG_LIST, &cont->child, 0,
2287 YANG_MUST, &cont->musts, 0,
2288 YANG_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2289 YANG_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2290 YANG_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2291 YANG_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2292 YANG_TYPEDEF, &cont->typedefs, 0,
2293 YANG_USES, &cont->child, 0,
2294 YANG_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2295 YANG_CUSTOM, NULL, 0
2296 ));
2297 ret = yin_parse_content(ctx, subelems, 21, data, YANG_CONTAINER, NULL, &cont->exts);
2298 subelems_deallocator(21, subelems);
2299 LY_CHECK_RET(ret);
2300
David Sedlákf111bcb2019-07-23 17:15:51 +02002301 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2302
2303 return LY_SUCCESS;
2304}
2305
2306/**
David Sedlák5379d392019-07-24 10:42:03 +02002307 * @brief Parse case element.
2308 *
2309 * @param[in,out] ctx YIN parser context for logging and to store current state.
2310 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2311 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002312 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002313 *
2314 * @return LY_ERR values.
2315 */
2316static LY_ERR
2317yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2318 struct tree_node_meta *node_meta)
2319{
David Sedlák5379d392019-07-24 10:42:03 +02002320 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002321 LY_ERR ret = LY_SUCCESS;
2322 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002323
2324 /* create new case */
David Sedlák8d552d62019-08-06 15:29:05 +02002325 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, cas, next);
David Sedlák5379d392019-07-24 10:42:03 +02002326 cas->nodetype = LYS_CASE;
2327 cas->parent = node_meta->parent;
2328
David Sedlák5379d392019-07-24 10:42:03 +02002329 /* parse argument */
2330 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, YANG_CASE));
2331
2332 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002333 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
2334 YANG_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2335 YANG_ANYXML, &cas->child, 0,
2336 YANG_CHOICE, &cas->child, 0,
2337 YANG_CONTAINER, &cas->child, 0,
2338 YANG_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2339 YANG_IF_FEATURE, &cas->iffeatures, 0,
2340 YANG_LEAF, &cas->child, 0,
2341 YANG_LEAF_LIST, &cas->child, 0,
2342 YANG_LIST, &cas->child, 0,
2343 YANG_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2344 YANG_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2345 YANG_USES, &cas->child, 0,
2346 YANG_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2347 YANG_CUSTOM, NULL, 0
2348 ));
2349 ret = yin_parse_content(ctx, subelems, 14, data, YANG_CASE, NULL, &cas->exts);
2350 subelems_deallocator(14, subelems);
2351
2352 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002353}
2354
2355/**
David Sedlák05404f62019-07-24 14:11:53 +02002356 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002357 *
2358 * @param[in,out] ctx YIN parser context for logging and to store current state.
2359 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2360 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002361 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002362 *
2363 * @return LY_ERR values.
2364 */
2365LY_ERR
2366yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2367 struct tree_node_meta *node_meta)
2368{
David Sedlák81497a32019-08-13 16:56:26 +02002369 LY_ERR ret = LY_SUCCESS;
2370 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002371 struct lysp_node_choice *choice;
2372
2373 /* create new choice */
David Sedlák8d552d62019-08-06 15:29:05 +02002374 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, choice, next);
2375
David Sedlákb7abcfa2019-07-24 12:33:35 +02002376 choice->nodetype = LYS_CHOICE;
2377 choice->parent = node_meta->parent;
2378
David Sedlákb7abcfa2019-07-24 12:33:35 +02002379 /* parse argument */
2380 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, YANG_CHOICE));
2381
2382 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002383 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
2384 YANG_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2385 YANG_ANYXML, &choice->child, 0,
2386 YANG_CASE, &choice->child, 0,
2387 YANG_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2388 YANG_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2389 YANG_CONTAINER, &choice->child, 0,
2390 YANG_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2391 YANG_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2392 YANG_IF_FEATURE, &choice->iffeatures, 0,
2393 YANG_LEAF, &choice->child, 0,
2394 YANG_LEAF_LIST, &choice->child, 0,
2395 YANG_LIST, &choice->child, 0,
2396 YANG_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2397 YANG_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2398 YANG_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2399 YANG_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2400 YANG_CUSTOM, NULL, 0
2401 ));
2402 ret = yin_parse_content(ctx, subelems, 17, data, YANG_CHOICE, NULL, &choice->exts);
2403 subelems_deallocator(17, subelems);
2404 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002405}
2406
2407/**
David Sedlák05404f62019-07-24 14:11:53 +02002408 * @brief Parse input or output element.
2409 *
2410 * @param[in,out] ctx YIN parser context for logging and to store current state.
2411 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2412 * @param[in,out] data Data to read from, always moved to currently handled character.
2413 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2414 *
2415 * @return LY_ERR values.
2416 */
2417static LY_ERR
2418yin_parse_inout(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword inout_kw,
2419 struct inout_meta *inout_meta)
2420{
David Sedlák81497a32019-08-13 16:56:26 +02002421 LY_ERR ret = LY_SUCCESS;
2422 struct yin_subelement *subelems = NULL;
2423
David Sedlák05404f62019-07-24 14:11:53 +02002424 /* initiate structure */
2425 inout_meta->inout_p->nodetype = (inout_kw == YANG_INPUT) ? LYS_INPUT : LYS_OUTPUT;
2426 inout_meta->inout_p->parent = inout_meta->parent;
2427
2428 /* check attributes */
2429 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
2430
2431 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002432 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
2433 YANG_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2434 YANG_ANYXML, &inout_meta->inout_p->data, 0,
2435 YANG_CHOICE, &inout_meta->inout_p->data, 0,
2436 YANG_CONTAINER, &inout_meta->inout_p->data, 0,
2437 YANG_GROUPING, &inout_meta->inout_p->groupings, 0,
2438 YANG_LEAF, &inout_meta->inout_p->data, 0,
2439 YANG_LEAF_LIST, &inout_meta->inout_p->data, 0,
2440 YANG_LIST, &inout_meta->inout_p->data, 0,
2441 YANG_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2442 YANG_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2443 YANG_USES, &inout_meta->inout_p->data, 0,
2444 YANG_CUSTOM, NULL, 0
2445 ));
2446 ret = yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts);
2447 subelems_deallocator(12, subelems);
2448 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002449
2450 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002451 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 +02002452
2453 return LY_SUCCESS;
2454}
2455
David Sedlák992fb7c2019-07-24 16:51:01 +02002456/**
2457 * @brief Parse action element.
2458 *
2459 * @param[in,out] ctx YIN parser context for logging and to store current state.
2460 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2461 * @param[in,out] data Data to read from, always moved to currently handled character.
2462 * @param[in] act_meta Meta information about parent node and actions to add to.
2463 *
2464 * @return LY_ERR values.
2465 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002466static LY_ERR
2467yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002468 struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002469{
David Sedlák81497a32019-08-13 16:56:26 +02002470 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->siblings;
2471 LY_ERR ret = LY_SUCCESS;
2472 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002473
2474 /* create new action */
David Sedlák6881b512019-08-13 12:52:00 +02002475 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *acts, act, LY_EMEM);
David Sedlák85d0eca2019-07-24 15:15:21 +02002476 act->nodetype = LYS_ACTION;
2477 act->parent = act_meta->parent;
2478
2479 /* parse argument */
2480 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, YANG_ACTION));
2481
2482 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002483 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
2484 YANG_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2485 YANG_GROUPING, &act->groupings, 0,
2486 YANG_IF_FEATURE, &act->iffeatures, 0,
2487 YANG_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2488 YANG_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2489 YANG_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2490 YANG_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2491 YANG_TYPEDEF, &act->typedefs, 0,
2492 YANG_CUSTOM, NULL, 0
2493 ));
2494 ret = (yin_parse_content(ctx, subelems, 9, data, YANG_ACTION, NULL, &act->exts));
2495 subelems_deallocator(9, subelems);
2496 LY_CHECK_RET(ret);
2497
David Sedlák85d0eca2019-07-24 15:15:21 +02002498 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2499
2500 return LY_SUCCESS;
2501}
2502
David Sedlák05404f62019-07-24 14:11:53 +02002503/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002504 * @brief Parse augment element.
2505 *
2506 * @param[in,out] ctx YIN parser context for logging and to store current state.
2507 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2508 * @param[in,out] data Data to read from, always moved to currently handled character.
2509 * @param[in] aug_meta Meta information about parent node and augments to add to.
2510 *
2511 * @return LY_ERR values.
2512 */
2513static LY_ERR
2514yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002515 struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002516{
2517 struct lysp_augment *aug;
David Sedlák6881b512019-08-13 12:52:00 +02002518 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->siblings;
David Sedlák81497a32019-08-13 16:56:26 +02002519 LY_ERR ret = LY_SUCCESS;
2520 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002521
2522 /* create new augment */
David Sedlák6881b512019-08-13 12:52:00 +02002523 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002524 aug->nodetype = LYS_AUGMENT;
2525 aug->parent = aug_meta->parent;
2526
2527 /* parse argument */
2528 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, YANG_AUGMENT));
2529 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2530
2531 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002532 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
2533 YANG_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2534 YANG_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2535 YANG_ANYXML, &aug->child, 0,
2536 YANG_CASE, &aug->child, 0,
2537 YANG_CHOICE, &aug->child, 0,
2538 YANG_CONTAINER, &aug->child, 0,
2539 YANG_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2540 YANG_IF_FEATURE, &aug->iffeatures, 0,
2541 YANG_LEAF, &aug->child, 0,
2542 YANG_LEAF_LIST, &aug->child, 0,
2543 YANG_LIST, &aug->child, 0,
2544 YANG_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2545 YANG_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2546 YANG_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2547 YANG_USES, &aug->child, 0,
2548 YANG_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2549 YANG_CUSTOM, NULL, 0
2550 ));
2551 ret = yin_parse_content(ctx, subelems, 17, data, YANG_AUGMENT, NULL, &aug->exts);
2552 subelems_deallocator(17, subelems);
2553 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002554
2555 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2556
2557 return LY_SUCCESS;
2558}
2559
David Sedlák8b754462019-07-25 16:22:13 +02002560/**
2561 * @brief Parse deviate element.
2562 *
2563 * @param[in,out] ctx YIN parser context for logging and to store current state.
2564 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2565 * @param[in,out] data Data to read from, always moved to currently handled character.
2566 * @param[in] deviates Deviates to add to.
2567 *
2568 * @return LY_ERR values.
2569 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002570static LY_ERR
2571yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2572 struct lysp_deviate **deviates)
2573{
2574 LY_ERR ret = LY_SUCCESS;
2575 uint8_t dev_mod;
2576 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002577 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002578 struct lysp_deviate_add *d_add = NULL;
2579 struct lysp_deviate_rpl *d_rpl = NULL;
2580 struct lysp_deviate_del *d_del = NULL;
2581
2582 /* parse argument */
2583 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_DEVIATE));
2584
2585 if (strcmp(temp_val, "not-supported") == 0) {
2586 dev_mod = LYS_DEV_NOT_SUPPORTED;
2587 } else if (strcmp(temp_val, "add") == 0) {
2588 dev_mod = LYS_DEV_ADD;
2589 } else if (strcmp(temp_val, "replace") == 0) {
2590 dev_mod = LYS_DEV_REPLACE;
2591 } else if (strcmp(temp_val, "delete") == 0) {
2592 dev_mod = LYS_DEV_DELETE;
2593 } else {
David Sedlák1538a842019-08-08 15:38:51 +02002594 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "deviate");
David Sedlák4ffcec82019-07-25 15:10:21 +02002595 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2596 return LY_EVALID;
2597 }
2598 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2599
2600 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2601 d = calloc(1, sizeof *d);
2602 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2603 struct yin_subelement subelems[1] = {
2604 {YANG_CUSTOM, NULL, 0}
2605 };
2606 ret = yin_parse_content(ctx, subelems, 1, data, YANG_DEVIATE, NULL, &d->exts);
2607
2608 } else if (dev_mod == LYS_DEV_ADD) {
2609 d_add = calloc(1, sizeof *d_add);
2610 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2611 d = (struct lysp_deviate *)d_add;
2612 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2613 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2614 struct yin_subelement subelems[9] = {
2615 {YANG_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2616 {YANG_DEFAULT, &d_add->dflts, 0},
2617 {YANG_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2618 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2619 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2620 {YANG_MUST, &d_add->musts, 0},
2621 {YANG_UNIQUE, &d_add->uniques, 0},
2622 {YANG_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2623 {YANG_CUSTOM, NULL, 0},
2624 };
2625 ret = yin_parse_content(ctx, subelems, 9, data, YANG_DEVIATE, NULL, &d_add->exts);
2626
2627 } else if (dev_mod == LYS_DEV_REPLACE) {
2628 d_rpl = calloc(1, sizeof *d_rpl);
2629 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2630 d = (struct lysp_deviate *)d_rpl;
2631 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2632 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2633 struct yin_subelement subelems[8] = {
2634 {YANG_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2635 {YANG_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2636 {YANG_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2637 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2638 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2639 {YANG_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2640 {YANG_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2641 {YANG_CUSTOM, NULL, 0},
2642 };
2643 ret = yin_parse_content(ctx, subelems, 8, data, YANG_DEVIATE, NULL, &d_rpl->exts);
2644
2645 } else {
2646 d_del = calloc(1, sizeof *d_del);
2647 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2648 d = (struct lysp_deviate *)d_del;
2649 struct yin_subelement subelems[5] = {
2650 {YANG_DEFAULT, &d_del->dflts, 0},
2651 {YANG_MUST, &d_del->musts, 0},
2652 {YANG_UNIQUE, &d_del->uniques, 0},
2653 {YANG_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2654 {YANG_CUSTOM, NULL, 0},
2655 };
2656 ret = yin_parse_content(ctx, subelems, 5, data, YANG_DEVIATE, NULL, &d_del->exts);
2657 }
2658 LY_CHECK_GOTO(ret, cleanup);
2659
2660 d->mod = dev_mod;
2661 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002662 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002663
2664 return ret;
2665
2666cleanup:
2667 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002668 return ret;
2669}
2670
David Sedlák992fb7c2019-07-24 16:51:01 +02002671/**
David Sedlák8b754462019-07-25 16:22:13 +02002672 * @brief Parse deviation element.
2673 *
2674 * @param[in,out] ctx YIN parser context for logging and to store current state.
2675 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2676 * @param[in,out] data Data to read from, always moved to currently handled character.
2677 * @param[in] deviations Deviations to add to.
2678 *
2679 * @return LY_ERR values.
2680 */
2681static LY_ERR
2682yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2683 struct lysp_deviation **deviations)
2684{
2685 struct lysp_deviation *dev;
2686
2687 /* create new deviation */
2688 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2689
2690 /* parse argument */
David Sedlák1538a842019-08-08 15:38:51 +02002691 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 +02002692 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2693 struct yin_subelement subelems[4] = {
2694 {YANG_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2695 {YANG_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2696 {YANG_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2697 {YANG_CUSTOM, NULL, 0},
2698 };
David Sedlák1538a842019-08-08 15:38:51 +02002699 return yin_parse_content(ctx, subelems, 4, data, YANG_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002700}
2701
2702/**
David Sedlákb4e44562019-07-04 15:42:12 +02002703 * @brief Map keyword type to substatement info.
2704 *
2705 * @param[in] kw Keyword type.
2706 *
2707 * @return correct LYEXT_SUBSTMT information.
2708 */
2709static LYEXT_SUBSTMT
2710kw2lyext_substmt(enum yang_keyword kw)
2711{
2712 switch (kw) {
2713 case YANG_ARGUMENT:
2714 return LYEXT_SUBSTMT_ARGUMENT;
2715 case YANG_BASE:
2716 return LYEXT_SUBSTMT_BASE;
2717 case YANG_BELONGS_TO:
2718 return LYEXT_SUBSTMT_BELONGSTO;
2719 case YANG_CONTACT:
2720 return LYEXT_SUBSTMT_CONTACT;
2721 case YANG_DEFAULT:
2722 return LYEXT_SUBSTMT_DEFAULT;
2723 case YANG_DESCRIPTION:
2724 return LYEXT_SUBSTMT_DESCRIPTION;
2725 case YANG_ERROR_APP_TAG:
2726 return LYEXT_SUBSTMT_ERRTAG;
2727 case YANG_ERROR_MESSAGE:
2728 return LYEXT_SUBSTMT_ERRMSG;
2729 case YANG_KEY:
2730 return LYEXT_SUBSTMT_KEY;
2731 case YANG_NAMESPACE:
2732 return LYEXT_SUBSTMT_NAMESPACE;
2733 case YANG_ORGANIZATION:
2734 return LYEXT_SUBSTMT_ORGANIZATION;
2735 case YANG_PATH:
2736 return LYEXT_SUBSTMT_PATH;
2737 case YANG_PREFIX:
2738 return LYEXT_SUBSTMT_PREFIX;
2739 case YANG_PRESENCE:
2740 return LYEXT_SUBSTMT_PRESENCE;
2741 case YANG_REFERENCE:
2742 return LYEXT_SUBSTMT_REFERENCE;
2743 case YANG_REVISION_DATE:
2744 return LYEXT_SUBSTMT_REVISIONDATE;
2745 case YANG_UNITS:
2746 return LYEXT_SUBSTMT_UNITS;
2747 case YANG_VALUE:
2748 return LYEXT_SUBSTMT_VALUE;
2749 case YANG_YANG_VERSION:
2750 return LYEXT_SUBSTMT_VERSION;
2751 case YANG_MODIFIER:
2752 return LYEXT_SUBSTMT_MODIFIER;
2753 case YANG_REQUIRE_INSTANCE:
2754 return LYEXT_SUBSTMT_REQINSTANCE;
2755 case YANG_YIN_ELEMENT:
2756 return LYEXT_SUBSTMT_YINELEM;
2757 case YANG_CONFIG:
2758 return LYEXT_SUBSTMT_CONFIG;
2759 case YANG_MANDATORY:
2760 return LYEXT_SUBSTMT_MANDATORY;
2761 case YANG_ORDERED_BY:
2762 return LYEXT_SUBSTMT_ORDEREDBY;
2763 case YANG_STATUS:
2764 return LYEXT_SUBSTMT_STATUS;
2765 case YANG_FRACTION_DIGITS:
2766 return LYEXT_SUBSTMT_FRACDIGITS;
2767 case YANG_MAX_ELEMENTS:
2768 return LYEXT_SUBSTMT_MAX;
2769 case YANG_MIN_ELEMENTS:
2770 return LYEXT_SUBSTMT_MIN;
2771 case YANG_POSITION:
2772 return LYEXT_SUBSTMT_POSITION;
2773 case YANG_UNIQUE:
2774 return LYEXT_SUBSTMT_UNIQUE;
2775 case YANG_IF_FEATURE:
2776 return LYEXT_SUBSTMT_IFFEATURE;
2777 default:
2778 return LYEXT_SUBSTMT_SELF;
2779 }
2780}
2781
David Sedlákc5b20842019-08-13 10:18:31 +02002782/**
2783 * @brief map keyword to keyword-group.
2784 *
2785 * @param[in] ctx YIN parser context used for logging.
2786 * @param[in] kw Keyword that is child of module or submodule.
2787 * @param[out] group Group of keyword.
2788 *
2789 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2790 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002791static LY_ERR
2792kw2kw_group(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_module_stmt *group)
2793{
2794 switch (kw) {
2795 /* module header */
2796 case YANG_NONE:
2797 case YANG_NAMESPACE:
2798 case YANG_PREFIX:
2799 case YANG_BELONGS_TO:
2800 case YANG_YANG_VERSION:
2801 *group = Y_MOD_MODULE_HEADER;
2802 break;
2803 /* linkage */
2804 case YANG_INCLUDE:
2805 case YANG_IMPORT:
2806 *group = Y_MOD_LINKAGE;
2807 break;
2808 /* meta */
2809 case YANG_ORGANIZATION:
2810 case YANG_CONTACT:
2811 case YANG_DESCRIPTION:
2812 case YANG_REFERENCE:
2813 *group = Y_MOD_META;
2814 break;
2815 /* revision */
2816 case YANG_REVISION:
2817 *group = Y_MOD_REVISION;
2818 break;
2819 /* body */
2820 case YANG_ANYDATA:
2821 case YANG_ANYXML:
2822 case YANG_AUGMENT:
2823 case YANG_CHOICE:
2824 case YANG_CONTAINER:
2825 case YANG_DEVIATION:
2826 case YANG_EXTENSION:
2827 case YANG_FEATURE:
2828 case YANG_GROUPING:
2829 case YANG_IDENTITY:
2830 case YANG_LEAF:
2831 case YANG_LEAF_LIST:
2832 case YANG_LIST:
2833 case YANG_NOTIFICATION:
2834 case YANG_RPC:
2835 case YANG_TYPEDEF:
2836 case YANG_USES:
2837 case YANG_CUSTOM:
2838 *group = Y_MOD_BODY;
2839 break;
2840 default:
2841 LOGINT(ctx->xml_ctx.ctx);
2842 return LY_EINT;
2843 }
2844
2845 return LY_SUCCESS;
2846}
2847
David Sedlákc5b20842019-08-13 10:18:31 +02002848/**
2849 * @brief Check if relative order of two keywords is valid.
2850 *
2851 * @param[in] ctx YIN parser context used for logging.
2852 * @param[in] kw Current keyword.
2853 * @param[in] next_kw Next keyword.
2854 * @param[in] parrent Identification of parrent element, can be se to to YANG_MODULE of YANG_SUBMODULE,
2855 * because relative order is required only in module and submodule sub-elements, used for logging.
2856 *
2857 * @return LY_SUCCESS on succes and LY_EVALID if relative order is invalid.
2858 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002859static LY_ERR
2860yin_check_relative_order(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_keyword next_kw, enum yang_keyword parrent)
2861{
2862 assert(parrent == YANG_MODULE || parrent == YANG_SUBMODULE);
2863 enum yang_module_stmt gr, next_gr;
2864
2865 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2866 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2867
2868 if (gr > next_gr) {
2869 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2870 return LY_EVALID;
2871 }
2872
2873 return LY_SUCCESS;
2874}
2875
David Sedlákd6e56892019-07-01 15:40:24 +02002876LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002877yin_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 +02002878 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 +02002879{
2880 LY_ERR ret = LY_SUCCESS;
David Sedlák8e7bda82019-07-16 17:57:50 +02002881 char *out = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +02002882 const char *prefix, *name;
2883 size_t out_len = 0, prefix_len, name_len;
David Sedlák8e7bda82019-07-16 17:57:50 +02002884 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002885 struct yin_arg_record *attrs = NULL;
David Sedláke6cd89e2019-08-07 12:46:02 +02002886 enum yang_keyword kw = YANG_NONE, last_kw = YANG_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002887 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002888
David Sedlákb0faad82019-07-04 14:28:59 +02002889 assert(is_ordered(subelem_info, subelem_info_size));
David Sedlákd6e56892019-07-01 15:40:24 +02002890
David Sedlákda8ffa32019-07-08 14:17:10 +02002891 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2892 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002893 /* current element has subelements as content */
2894 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002895 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákc5b20842019-08-13 10:18:31 +02002896 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákd6e56892019-07-01 15:40:24 +02002897 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +02002898 if (!name) {
David Sedlákd6e56892019-07-01 15:40:24 +02002899 /* end of current element reached */
2900 break;
2901 }
David Sedlák1af868e2019-07-17 17:03:14 +02002902 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002903 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6cd89e2019-08-07 12:46:02 +02002904 last_kw = kw;
David Sedlákc5b20842019-08-13 10:18:31 +02002905 kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002906
2907 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002908 subelem = get_record(kw, subelem_info_size, subelem_info);
2909 if (!subelem) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002910 if (current_element == YANG_DEVIATE && isdevsub(kw)) {
2911 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2912 } else {
David Sedlákc5b20842019-08-13 10:18:31 +02002913 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 +02002914 }
David Sedlákd6e56892019-07-01 15:40:24 +02002915 ret = LY_EVALID;
2916 goto cleanup;
2917 }
2918
David Sedlák6542aed2019-08-14 10:47:43 +02002919 /* relative order is required only in module and submodule sub-elements */
David Sedláke6cd89e2019-08-07 12:46:02 +02002920 if (current_element == YANG_MODULE || current_element == YANG_SUBMODULE) {
2921 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2922 LY_CHECK_GOTO(ret, cleanup);
2923 }
David Sedlák5f8191e2019-07-08 16:35:52 +02002924
David Sedlák4ffcec82019-07-25 15:10:21 +02002925 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002926 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002927 /* subelement uniquenes */
David Sedlák1538a842019-08-08 15:38:51 +02002928 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 +02002929 return LY_EVALID;
2930 }
David Sedlák1af868e2019-07-17 17:03:14 +02002931 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002932 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002933 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002934 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002935 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002936 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002937 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002938 if (ctx->mod_version < 2) {
David Sedlák1538a842019-08-08 15:38:51 +02002939 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 +02002940 ret = LY_EVALID;
2941 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002942 }
2943 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002944 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002945 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002946
David Sedlákd6e56892019-07-01 15:40:24 +02002947 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002948 /* call responsible function */
David Sedlákd6e56892019-07-01 15:40:24 +02002949 case YANG_CUSTOM:
David Sedlákc5b20842019-08-13 10:18:31 +02002950 ret = yin_parse_extension_instance(ctx, attrs, data, name2fullname(name, prefix_len),
2951 namelen2fulllen(name_len, prefix_len),
David Sedlák1af868e2019-07-17 17:03:14 +02002952 kw2lyext_substmt(current_element),
2953 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002954 break;
2955 case YANG_ACTION:
David Sedlákeaa45792019-07-24 15:25:01 +02002956 case YANG_RPC:
David Sedlák6881b512019-08-13 12:52:00 +02002957 ret = yin_parse_action(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002958 break;
2959 case YANG_ANYDATA:
David Sedlákd6e56892019-07-01 15:40:24 +02002960 case YANG_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002961 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002962 break;
2963 case YANG_ARGUMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002964 ret = yin_parse_argument_element(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002965 break;
2966 case YANG_AUGMENT:
David Sedlák6881b512019-08-13 12:52:00 +02002967 ret = yin_parse_augment(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002968 break;
2969 case YANG_BASE:
David Sedlák6542aed2019-08-14 10:47:43 +02002970 ret = yin_parse_base(ctx, attrs, data, current_element, subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002971 break;
2972 case YANG_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002973 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002974 break;
2975 case YANG_BIT:
David Sedlák43801c92019-08-05 15:58:54 +02002976 ret = yin_parse_bit(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002977 break;
2978 case YANG_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002979 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002980 break;
2981 case YANG_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002982 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002983 break;
2984 case YANG_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02002985 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002986 break;
2987 case YANG_CONTACT:
David Sedlák619db942019-07-03 14:47:30 +02002988 case YANG_DESCRIPTION:
2989 case YANG_ORGANIZATION:
2990 case YANG_REFERENCE:
David Sedlákdf2a9732019-08-07 13:23:16 +02002991 ret = yin_parse_meta_element(ctx, attrs, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002992 break;
2993 case YANG_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02002994 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002995 break;
2996 case YANG_DEFAULT:
David Sedlák6542aed2019-08-14 10:47:43 +02002997 case YANG_ERROR_APP_TAG:
2998 case YANG_KEY:
2999 case YANG_PRESENCE:
3000 ret = yin_parse_simple_elem(ctx, attrs, data, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003001 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003002 case YANG_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02003003 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003004 break;
3005 case YANG_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02003006 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003007 break;
David Sedlák43801c92019-08-05 15:58:54 +02003008 case YANG_ENUM:
3009 ret = yin_parse_enum(ctx, attrs, data, (struct lysp_type *)subelem->dest);
3010 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003011 case YANG_ERROR_MESSAGE:
David Sedlákdf2a9732019-08-07 13:23:16 +02003012 ret = yin_parse_err_msg_element(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003013 break;
3014 case YANG_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003015 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003016 break;
3017 case YANG_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02003018 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003019 break;
3020 case YANG_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02003021 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003022 break;
3023 case YANG_GROUPING:
David Sedlák6881b512019-08-13 12:52:00 +02003024 ret = yin_parse_grouping(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003025 break;
3026 case YANG_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02003027 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003028 break;
3029 case YANG_IF_FEATURE:
David Sedlák6542aed2019-08-14 10:47:43 +02003030 case YANG_UNITS:
3031 ret = yin_parse_simple_elem(ctx, attrs, data, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003032 break;
3033 case YANG_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02003034 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003035 break;
3036 case YANG_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02003037 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003038 break;
3039 case YANG_INPUT:
David Sedlák05404f62019-07-24 14:11:53 +02003040 case YANG_OUTPUT:
3041 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003042 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003043 case YANG_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02003044 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003045 break;
3046 case YANG_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02003047 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003048 break;
3049 case YANG_LENGTH:
David Sedlák6542aed2019-08-14 10:47:43 +02003050 ret = yin_parse_length(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003051 break;
3052 case YANG_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02003053 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003054 break;
3055 case YANG_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02003056 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003057 break;
3058 case YANG_MAX_ELEMENTS:
David Sedlákd6e56892019-07-01 15:40:24 +02003059 case YANG_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02003060 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003061 break;
3062 case YANG_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02003063 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003064 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003065 case YANG_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02003066 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003067 break;
3068 case YANG_NAMESPACE:
David Sedlák6542aed2019-08-14 10:47:43 +02003069 ret = yin_parse_simple_elem(ctx, attrs, data, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003070 break;
3071 case YANG_NOTIFICATION:
David Sedlák6881b512019-08-13 12:52:00 +02003072 ret = yin_parse_notification(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003073 break;
3074 case YANG_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02003075 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003076 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003077 case YANG_PATH:
David Sedlák6542aed2019-08-14 10:47:43 +02003078 ret = yin_parse_path(ctx, attrs, data, kw, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003079 break;
3080 case YANG_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02003081 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003082 break;
David Sedlák5545f5d2019-07-11 11:55:16 +02003083 case YANG_VALUE:
David Sedlákd6e56892019-07-01 15:40:24 +02003084 case YANG_POSITION:
David Sedlák6542aed2019-08-14 10:47:43 +02003085 ret = yin_parse_value_pos_element(ctx, attrs, data, kw, (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003086 break;
3087 case YANG_PREFIX:
David Sedlák6542aed2019-08-14 10:47:43 +02003088 ret = yin_parse_simple_elem(ctx, attrs, data, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003089 break;
3090 case YANG_RANGE:
David Sedlák6542aed2019-08-14 10:47:43 +02003091 ret = yin_parse_range(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003092 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003093 case YANG_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02003094 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003095 break;
3096 case YANG_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02003097 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003098 break;
3099 case YANG_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02003100 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003101 break;
3102 case YANG_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02003103 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003104 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003105 case YANG_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02003106 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003107 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003108 case YANG_TYPE:
David Sedlák6542aed2019-08-14 10:47:43 +02003109 ret = yin_parse_type(ctx, attrs, data, current_element, subelem);
David Sedlákd6e56892019-07-01 15:40:24 +02003110 break;
3111 case YANG_TYPEDEF:
David Sedlák6881b512019-08-13 12:52:00 +02003112 ret = yin_parse_typedef(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003113 break;
3114 case YANG_UNIQUE:
David Sedlák6542aed2019-08-14 10:47:43 +02003115 ret = yin_parse_simple_elem(ctx, attrs, data, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003116 break;
3117 case YANG_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02003118 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003119 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003120 case YANG_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02003121 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003122 break;
3123 case YANG_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003124 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003125 break;
3126 case YANG_YIN_ELEMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02003127 ret = yin_parse_yin_element_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02003128 break;
3129 case YIN_TEXT:
David Sedlák3ffbc522019-07-02 17:49:28 +02003130 case YIN_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02003131 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02003132 break;
3133 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02003134 LOGINT(ctx->xml_ctx.ctx);
David Sedlák21f87cd2019-07-03 16:53:23 +02003135 return LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02003136 }
David Sedlák3ffbc522019-07-02 17:49:28 +02003137 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02003138 FREE_ARRAY(ctx, attrs, free_arg_rec);
3139 attrs = NULL;
3140 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02003141 }
3142 } else {
3143 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02003144 /* save text content, if text_content isn't set, it's just ignored */
David Sedlákc5b20842019-08-13 10:18:31 +02003145 /* no resources are allocated in this branch, no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02003146 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02003147 if (text_content) {
3148 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003149 *text_content = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák3ffbc522019-07-02 17:49:28 +02003150 if (!*text_content) {
3151 free(out);
3152 return LY_EMEM;
3153 }
3154 } else {
3155 if (out_len == 0) {
David Sedlák99295322019-07-17 11:34:18 +02003156 *text_content = lydict_insert(ctx->xml_ctx.ctx, "", 0);
David Sedlák3ffbc522019-07-02 17:49:28 +02003157 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003158 *text_content = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák3ffbc522019-07-02 17:49:28 +02003159 }
3160 }
3161 }
David Sedlákd6e56892019-07-01 15:40:24 +02003162 /* load closing element */
David Sedlákc5b20842019-08-13 10:18:31 +02003163 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákd6e56892019-07-01 15:40:24 +02003164 }
3165 }
David Sedlák8b754462019-07-25 16:22:13 +02003166 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3167 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003168
3169cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02003170 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02003171 return ret;
3172}
3173
David Sedlák619db942019-07-03 14:47:30 +02003174LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02003175yin_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 +02003176 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003177{
3178 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003179 char *out;
3180 const char *name, *prefix;
3181 size_t out_len, prefix_len, name_len;
3182 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003183 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003184 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
3185 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003186
David Sedlákda8ffa32019-07-08 14:17:10 +02003187 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003188
3189 e->yin = 0;
3190 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02003191 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02003192 e->insubstmt = subelem;
3193 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003194 e->yin |= LYS_YIN;
3195
David Sedlákb1a78352019-06-28 16:16:29 +02003196 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02003197 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02003198 if (!iter->prefix) {
3199 new_subelem = calloc(1, sizeof(*new_subelem));
3200 if (!e->child) {
3201 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003202 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003203 last_subelem->next = new_subelem;
3204 }
3205 last_subelem = new_subelem;
3206
3207 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003208 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
3209 LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003210 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003211 last_subelem->arg = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
3212 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003213 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003214 last_subelem->arg = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
3215 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003216 }
3217 }
3218 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003219
David Sedlákf250ecf2019-07-01 11:02:05 +02003220 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003221 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3222 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003223 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003224 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3225 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02003226 if (!name) {
3227 /* end of extension instance reached */
3228 break;
3229 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003230 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02003231 if (!e->child) {
3232 e->child = new_subelem;
3233 } else {
3234 last_subelem->next = new_subelem;
3235 }
3236 last_subelem = new_subelem;
3237 }
David Sedlák555c7202019-07-04 12:14:12 +02003238 } else {
3239 /* save text content */
3240 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003241 e->argument = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák555c7202019-07-04 12:14:12 +02003242 if (!e->argument) {
3243 free(out);
3244 return LY_EMEM;
3245 }
3246 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003247 e->argument = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02003248 LY_CHECK_RET(!e->argument, LY_EMEM);
3249 }
David Sedlákda8ffa32019-07-08 14:17:10 +02003250 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlák555c7202019-07-04 12:14:12 +02003251 LY_CHECK_RET(name, LY_EINT);
David Sedlákb1a78352019-06-28 16:16:29 +02003252 }
David Sedlákb1a78352019-06-28 16:16:29 +02003253 }
3254
3255 return LY_SUCCESS;
3256}
3257
3258LY_ERR
David Sedlák4ffcec82019-07-25 15:10:21 +02003259yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char **data,
3260 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02003261{
3262 LY_ERR ret = LY_SUCCESS;
3263 const char *temp_prefix, *temp_name;
3264 char *out = NULL;
David Sedlák4ffcec82019-07-25 15:10:21 +02003265 size_t out_len, temp_name_len, temp_prefix_len, prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02003266 int dynamic;
3267 struct yin_arg_record *subelem_args = NULL;
3268 struct lysp_stmt *last = NULL, *new = NULL;
3269
3270 /* allocate new structure for element */
3271 *element = calloc(1, sizeof(**element));
David Sedlákda8ffa32019-07-08 14:17:10 +02003272 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, name, name_len);
3273 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003274
3275 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +02003276 /* load attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +02003277 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákb1a78352019-06-28 16:16:29 +02003278 /* add new element to linked-list */
3279 new = calloc(1, sizeof(*last));
David Sedlákda8ffa32019-07-08 14:17:10 +02003280 LY_CHECK_ERR_GOTO(ret, LOGMEM(ctx->xml_ctx.ctx), err);
David Sedlákb1a78352019-06-28 16:16:29 +02003281 if (!(*element)->child) {
3282 /* save first */
3283 (*element)->child = new;
3284 } else {
3285 last->next = new;
3286 }
3287 last = new;
3288
3289 last->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003290 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 +02003291 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003292 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003293 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003294 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
3295 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003296 /* attributes with prefix are ignored */
3297 if (!temp_prefix) {
3298 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003299 last->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlákb1a78352019-06-28 16:16:29 +02003300 if (!last->arg) {
3301 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02003302 LOGMEM(ctx->xml_ctx.ctx);
David Sedlákb1a78352019-06-28 16:16:29 +02003303 ret = LY_EMEM;
3304 goto err;
3305 }
3306 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003307 last->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
3308 LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003309 }
3310 }
3311 }
3312
3313 /* parse content of element */
David Sedlákda8ffa32019-07-08 14:17:10 +02003314 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003315 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003316 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákb1a78352019-06-28 16:16:29 +02003317 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003318 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 +02003319 LY_CHECK_GOTO(ret, err);
3320 if (!name) {
3321 /* end of element reached */
3322 break;
3323 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003324 ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, data, &last->next);
David Sedlákb1a78352019-06-28 16:16:29 +02003325 LY_CHECK_GOTO(ret, err);
3326 last = last->next;
3327 }
3328 } else {
3329 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +02003330 if (out_len != 0) {
3331 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003332 (*element)->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák5392a212019-07-01 09:19:10 +02003333 if (!(*element)->arg) {
3334 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02003335 LOGMEM(ctx->xml_ctx.ctx);
David Sedlák5392a212019-07-01 09:19:10 +02003336 ret = LY_EMEM;
3337 goto err;
3338 }
3339 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003340 (*element)->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
3341 LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003342 }
David Sedlákb1a78352019-06-28 16:16:29 +02003343 }
3344 /* read closing tag */
David Sedlákda8ffa32019-07-08 14:17:10 +02003345 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 +02003346 LY_CHECK_GOTO(ret, err);
3347 }
3348
David Sedlákda8ffa32019-07-08 14:17:10 +02003349 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlákb1a78352019-06-28 16:16:29 +02003350 return LY_SUCCESS;
3351
3352err:
David Sedlákda8ffa32019-07-08 14:17:10 +02003353 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003354 return ret;
3355}
3356
3357LY_ERR
David Sedlák4f03b932019-07-26 13:01:47 +02003358yin_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 +02003359{
David Sedlák81497a32019-08-13 16:56:26 +02003360 LY_ERR ret = LY_SUCCESS;
3361 struct yin_subelement *subelems = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003362
David Sedlák81497a32019-08-13 16:56:26 +02003363 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, YANG_MODULE));
3364 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
3365 YANG_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3366 YANG_ANYXML, &mod->data, 0,
3367 YANG_AUGMENT, &mod->augments, 0,
3368 YANG_CHOICE, &mod->data, 0,
3369 YANG_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3370 YANG_CONTAINER, &mod->data, 0,
3371 YANG_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3372 YANG_DEVIATION, &mod->deviations, 0,
3373 YANG_EXTENSION, &mod->extensions, 0,
3374 YANG_FEATURE, &mod->features, 0,
3375 YANG_GROUPING, &mod->groupings, 0,
3376 YANG_IDENTITY, &mod->identities, 0,
3377 YANG_IMPORT, mod->mod->prefix, &mod->imports, 0,
3378 YANG_INCLUDE, mod->mod->name, &mod->includes, 0,
3379 YANG_LEAF, &mod->data, 0,
3380 YANG_LEAF_LIST, &mod->data, 0,
3381 YANG_LIST, &mod->data, 0,
3382 YANG_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3383 YANG_NOTIFICATION, &mod->notifs, 0,
3384 YANG_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3385 YANG_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3386 YANG_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3387 YANG_REVISION, &mod->revs, 0,
3388 YANG_RPC, &mod->rpcs, 0,
3389 YANG_TYPEDEF, &mod->typedefs, 0,
3390 YANG_USES, &mod->data, 0,
3391 YANG_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3392 YANG_CUSTOM, NULL, 0
3393 ));
3394
3395 ret = yin_parse_content(ctx, subelems, 28, data, YANG_MODULE, NULL, &mod->exts);
3396 subelems_deallocator(28, subelems);
3397
3398 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003399}
3400
3401LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003402yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3403{
David Sedlák81497a32019-08-13 16:56:26 +02003404 LY_ERR ret = LY_SUCCESS;
3405 struct yin_subelement *subelems = NULL;
David Sedlák298ff6d2019-07-26 14:29:03 +02003406
David Sedlák81497a32019-08-13 16:56:26 +02003407 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, YANG_SUBMODULE));
3408 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
3409 YANG_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3410 YANG_ANYXML, &submod->data, 0,
3411 YANG_AUGMENT, &submod->augments, 0,
3412 YANG_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3413 YANG_CHOICE, &submod->data, 0,
3414 YANG_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3415 YANG_CONTAINER, &submod->data, 0,
3416 YANG_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3417 YANG_DEVIATION, &submod->deviations, 0,
3418 YANG_EXTENSION, &submod->extensions, 0,
3419 YANG_FEATURE, &submod->features, 0,
3420 YANG_GROUPING, &submod->groupings, 0,
3421 YANG_IDENTITY, &submod->identities, 0,
3422 YANG_IMPORT, submod->prefix, &submod->imports, 0,
3423 YANG_INCLUDE, submod->name, &submod->includes, 0,
3424 YANG_LEAF, &submod->data, 0,
3425 YANG_LEAF_LIST, &submod->data, 0,
3426 YANG_LIST, &submod->data, 0,
3427 YANG_NOTIFICATION, &submod->notifs, 0,
3428 YANG_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3429 YANG_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3430 YANG_REVISION, &submod->revs, 0,
3431 YANG_RPC, &submod->rpcs, 0,
3432 YANG_TYPEDEF, &submod->typedefs, 0,
3433 YANG_USES, &submod->data, 0,
3434 YANG_YANG_VERSION, &submod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3435 YANG_CUSTOM, NULL, 0
3436 ));
3437
3438 ret = yin_parse_content(ctx, subelems, 27, data, YANG_SUBMODULE, NULL, &submod->exts);
3439 subelems_deallocator(27, subelems);
3440
3441 return ret;
David Sedlák298ff6d2019-07-26 14:29:03 +02003442}
3443
3444LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02003445yin_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 +02003446{
3447 enum yang_keyword kw = YANG_NONE;
3448 LY_ERR ret = LY_SUCCESS;
3449 const char *prefix, *name;
3450 size_t prefix_len, name_len;
3451 struct yin_arg_record *attrs = NULL;
3452 struct lysp_submodule *mod_p = NULL;
3453
3454 /* create context */
3455 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003456 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003457 (*yin_ctx)->xml_ctx.ctx = ctx;
3458 (*yin_ctx)->xml_ctx.line = 1;
3459
David Sedlák1b623122019-08-05 15:27:49 +02003460 /* map the typedefs and groupings list from main context to the submodule's context */
3461 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3462 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3463
David Sedlák8985a142019-07-31 16:43:06 +02003464 /* check submodule */
3465 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3466 LY_CHECK_GOTO(ret, cleanup);
3467 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3468 LY_CHECK_GOTO(ret, cleanup);
3469 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
3470
3471 if (kw == YANG_MODULE) {
3472 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3473 ret = LY_EINVAL;
3474 goto cleanup;
3475 } else if (kw != YANG_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003476 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003477 ret = LY_EVALID;
3478 goto cleanup;
3479 }
3480
3481 mod_p = calloc(1, sizeof *mod_p);
3482 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3483 mod_p->parsing = 1;
3484
3485 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3486 LY_CHECK_GOTO(ret, cleanup);
3487
David Sedlák6d781b62019-08-02 15:22:52 +02003488 name = NULL;
3489 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3490 const char *temp_data = data;
3491 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3492 data = temp_data;
3493 }
3494 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
David Sedlák1538a842019-08-08 15:38:51 +02003495 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 +02003496 ret = LY_EVALID;
3497 goto cleanup;
3498 }
3499
David Sedlák8985a142019-07-31 16:43:06 +02003500 mod_p->parsing = 0;
3501 *submod = mod_p;
3502
3503cleanup:
3504 if (ret) {
3505 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003506 yin_parser_ctx_free(*yin_ctx);
3507 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003508 }
3509
3510 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3511 return ret;
3512}
3513
3514LY_ERR
3515yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003516{
David Sedláke4889912018-11-02 09:52:40 +01003517 LY_ERR ret = LY_SUCCESS;
3518 enum yang_keyword kw = YANG_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003519 struct lysp_module *mod_p = NULL;
3520 const char *prefix, *name;
3521 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003522 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003523
David Sedlák8985a142019-07-31 16:43:06 +02003524 /* create context */
3525 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003526 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003527 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
3528 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003529
David Sedlák8985a142019-07-31 16:43:06 +02003530 /* check module */
3531 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003532 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003533 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003534 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003535 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
David Sedláke4889912018-11-02 09:52:40 +01003536 if (kw == YANG_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003537 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 +01003538 ret = LY_EINVAL;
3539 goto cleanup;
3540 } else if (kw != YANG_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003541 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003542 ret = LY_EVALID;
3543 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003544 }
3545
David Sedlák3017da42019-02-15 09:48:04 +01003546 /* allocate module */
3547 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003548 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003549 mod_p->mod = mod;
3550 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003551
David Sedlák00250342019-06-21 14:19:39 +02003552 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003553 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003554 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003555
David Sedlák1b623122019-08-05 15:27:49 +02003556 /* check trailing characters */
David Sedlák6d781b62019-08-02 15:22:52 +02003557 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3558 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3559 }
3560 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
David Sedlák1538a842019-08-08 15:38:51 +02003561 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 +02003562
3563 ret = LY_EVALID;
3564 goto cleanup;
3565 }
3566
David Sedlák3017da42019-02-15 09:48:04 +01003567 mod_p->parsing = 0;
3568 mod->parsed = mod_p;
3569
3570cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003571 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003572 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003573 yin_parser_ctx_free(*yin_ctx);
3574 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003575 }
David Sedlák8985a142019-07-31 16:43:06 +02003576 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003577 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003578}