blob: 997be0748a5e7243c063bad841cce801697afe76 [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ák071f7662019-09-12 02:02:51 +020053 [YIN_ARG_NONE] = "none",
David Sedlákf6251182019-06-06 10:22:13 +020054};
55
Radek Krejcid6b76452019-09-03 17:03:03 +020056enum ly_stmt
David Sedlákc1771b12019-07-10 15:55:46 +020057yin_match_keyword(struct yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejcid6b76452019-09-03 17:03:03 +020058 const char *prefix, size_t prefix_len, enum ly_stmt parrent)
David Sedlák1bccdfa2019-06-17 15:55:27 +020059{
David Sedlák8f7a1172019-06-20 14:42:18 +020060 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +020061 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020062 const struct lyxml_ns *ns = NULL;
63
64 if (!name || name_len == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +020065 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +020066 }
67
David Sedlákda8ffa32019-07-08 14:17:10 +020068 ns = lyxml_ns_get(&ctx->xml_ctx, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +020069 if (ns) {
70 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +020071 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +020072 }
73 } else {
74 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +020075 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020076 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020077
David Sedlák8f7a1172019-06-20 14:42:18 +020078 start = name;
79 kw = lysp_match_kw(NULL, &name);
80
81 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +020082 /* this is done because of collision in yang statement value and yang argument mapped to yin element value */
Radek Krejcid6b76452019-09-03 17:03:03 +020083 if (kw == LY_STMT_VALUE && parrent == LY_STMT_ERROR_MESSAGE) {
84 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +020085 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020086 return kw;
87 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020088 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +020089 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +020090 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +020091 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +020092 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020093 }
94}
95
David Sedlákc5b20842019-08-13 10:18:31 +020096enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +020097yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020098{
David Sedlákc5b20842019-08-13 10:18:31 +020099 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200100 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200101 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200102
David Sedlák94de2aa2019-02-15 12:42:11 +0100103#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
104#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100105#define IF_ARG_PREFIX_END }
106
David Sedlák1c8b2702019-02-22 11:03:02 +0100107 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100108 case 'c':
109 already_read += 1;
110 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200111 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200112
David Sedlák94de2aa2019-02-15 12:42:11 +0100113 case 'd':
114 already_read += 1;
115 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200116 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200117
David Sedlák94de2aa2019-02-15 12:42:11 +0100118 case 'm':
119 already_read += 1;
120 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200121 break;
122
David Sedlák94de2aa2019-02-15 12:42:11 +0100123 case 'n':
124 already_read += 1;
125 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200126 break;
127
David Sedlák94de2aa2019-02-15 12:42:11 +0100128 case 't':
129 already_read += 1;
130 IF_ARG_PREFIX("a", 1)
131 IF_ARG("g", 1, YIN_ARG_TAG)
132 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
133 IF_ARG_PREFIX_END
134 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200135 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200136
David Sedlák94de2aa2019-02-15 12:42:11 +0100137 case 'u':
138 already_read += 1;
139 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200140 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200141
David Sedlák94de2aa2019-02-15 12:42:11 +0100142 case 'v':
143 already_read += 1;
144 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200145 break;
146 }
147
David Sedlákc10e7902018-12-17 02:17:59 +0100148 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200149 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200150 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200151 }
152
David Sedlák18730132019-03-15 15:51:34 +0100153#undef IF_ARG
154#undef IF_ARG_PREFIX
155#undef IF_ARG_PREFIX_END
156
David Sedlák872c7b42018-10-26 13:15:20 +0200157 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200158}
159
David Sedlák4f03b932019-07-26 13:01:47 +0200160void free_arg_rec(struct yin_parser_ctx *ctx, struct yin_arg_record *record) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200161 (void)ctx; /* unused */
David Sedlákd2d676a2019-07-22 11:28:19 +0200162 if (record && record->dynamic_content) {
David Sedlák00250342019-06-21 14:19:39 +0200163 free(record->content);
164 }
165}
166
Radek Krejcid6b76452019-09-03 17:03:03 +0200167#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
168 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
169 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
170 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200171
Radek Krejcid6b76452019-09-03 17:03:03 +0200172#define HAS_META(kw) (IS_NODE_ELEM(kw) || kw == LY_STMT_IMPORT || kw == LY_STMT_INCLUDE || kw == LY_STMT_INPUT || kw == LY_STMT_OUTPUT)
David Sedlák81497a32019-08-13 16:56:26 +0200173
David Sedlák26ea1432019-08-14 13:42:23 +0200174/**
175 * @brief Free subelems information allocated on heap.
176 *
177 * @param[in] count Size of subelems array.
178 * @param[in] subelems Subelems array to free.
179 */
David Sedlák81497a32019-08-13 16:56:26 +0200180static void
181subelems_deallocator(size_t count, struct yin_subelement *subelems)
182{
183 for(size_t i = 0; i < count; ++i) {
184 if (HAS_META(subelems[i].type)) {
185 free(subelems[i].dest);
186 }
187 }
188
189 free(subelems);
190}
191
David Sedlák26ea1432019-08-14 13:42:23 +0200192/**
193 * @brief Allocate subelems information on heap.
194 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200195 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200196 * @param[in] count Number of subelements.
197 * @param[in] parent Parent node if any.
198 * @param[out] result Allocated subelems array.
199 *
200 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
201 */
David Sedlák81497a32019-08-13 16:56:26 +0200202static LY_ERR
203subelems_allocator(struct yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
204 struct yin_subelement **result, ...)
205{
206 va_list ap;
207
208 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200209 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200210
211 va_start(ap, result);
212 for (size_t i = 0; i < count; ++i) {
213 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200214 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200215 /* DEST */
216 if (IS_NODE_ELEM((*result)[i].type)) {
217 struct tree_node_meta *node_meta = NULL;
218 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200219 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200220 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200221 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200222 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200223 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200224 struct import_meta *imp_meta = NULL;
225 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200226 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200227 imp_meta->prefix = va_arg(ap, const char *);
228 imp_meta->imports = va_arg(ap, struct lysp_import **);
229 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200230 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200231 struct include_meta *inc_meta = NULL;
232 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200233 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200234 inc_meta->name = va_arg(ap, const char *);
235 inc_meta->includes = va_arg(ap, struct lysp_include **);
236 (*result)[i].dest = inc_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200237 } else if ((*result)[i].type == LY_STMT_INPUT || (*result)[i].type == LY_STMT_OUTPUT) {
David Sedlák81497a32019-08-13 16:56:26 +0200238 struct inout_meta *inout_meta = NULL;
239 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200240 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200241 inout_meta->parent = parent;
242 inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
243 (*result)[i].dest = inout_meta;
244 } else {
245 (*result)[i].dest = va_arg(ap, void *);
246 }
247 /* FLAGS */
248 (*result)[i].flags = va_arg(ap, int);
249 }
250 va_end(ap);
251
252 return LY_SUCCESS;
253
David Sedlákbf8a2b72019-08-14 16:48:10 +0200254mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200255 subelems_deallocator(count, *result);
256 LOGMEM(ctx->xml_ctx.ctx);
257 return LY_EMEM;
258}
259
David Sedlák8f7a1172019-06-20 14:42:18 +0200260LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200261yin_load_attributes(struct yin_parser_ctx *ctx, const char **data, struct yin_arg_record **attrs)
David Sedláka7406952019-04-05 10:33:07 +0200262{
263 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200264 struct yin_arg_record *argument_record = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +0200265 const char *prefix, *name;
266 size_t prefix_len, name_len;
David Sedláka7406952019-04-05 10:33:07 +0200267
David Sedlák555c7202019-07-04 12:14:12 +0200268 /* load all attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +0200269 while (ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákc5b20842019-08-13 10:18:31 +0200270 ret = lyxml_get_attribute(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák26ea1432019-08-14 13:42:23 +0200271 LY_CHECK_GOTO(ret, cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200272
David Sedlákda8ffa32019-07-08 14:17:10 +0200273 if (ctx->xml_ctx.status == LYXML_ATTR_CONTENT) {
274 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, *attrs, argument_record, ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +0200275 argument_record->name = name;
276 argument_record->name_len = name_len;
277 argument_record->prefix = prefix;
278 argument_record->prefix_len = prefix_len;
David Sedlákda8ffa32019-07-08 14:17:10 +0200279 ret = lyxml_get_string(&ctx->xml_ctx, data, &argument_record->content, &argument_record->content_len,
David Sedlák57715b12019-06-17 13:05:22 +0200280 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák26ea1432019-08-14 13:42:23 +0200281 LY_CHECK_GOTO(ret, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200282 }
283 }
284
David Sedlák8f7a1172019-06-20 14:42:18 +0200285cleanup:
286 if (ret != LY_SUCCESS) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200287 FREE_ARRAY(ctx, *attrs, free_arg_rec);
David Sedlákb4e44562019-07-04 15:42:12 +0200288 *attrs = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200289 }
290 return ret;
291}
292
David Sedlák4a650532019-07-10 11:55:18 +0200293LY_ERR
294yin_validate_value(struct yin_parser_ctx *ctx, enum yang_arg val_type, char *val, size_t len)
295{
296 int prefix = 0;
297 unsigned int c;
298 size_t utf8_char_len;
299 size_t already_read = 0;
300 while (already_read < len) {
301 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
302 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
303 already_read += utf8_char_len;
304 LY_CHECK_ERR_RET(already_read > len, LOGINT(ctx->xml_ctx.ctx), LY_EINT);
305
306 switch (val_type) {
307 case Y_IDENTIF_ARG:
308 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
309 break;
310 case Y_PREF_IDENTIF_ARG:
311 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
312 break;
313 case Y_STR_ARG:
314 case Y_MAYBE_STR_ARG:
315 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
316 break;
317 }
318 }
319
320 return LY_SUCCESS;
321}
322
David Sedlákb4e44562019-07-04 15:42:12 +0200323/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200324 * @brief Parse yin attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200325 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200326 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200327 * @param[in] attrs ([Sized array](@ref sizedarrays)) of attributes.
David Sedlák4a650532019-07-10 11:55:18 +0200328 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
329 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200330 * @param[out] arg_val Where value of argument should be stored. Can be NULL iff arg_type is specified as YIN_ARG_NONE.
David Sedlák292763b2019-07-09 11:10:53 +0200331 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200332 * @param[in] current_element Identification of current element, used for logging.
333 *
334 * @return LY_ERR values.
335 */
336static LY_ERR
David Sedlákc5b20842019-08-13 10:18:31 +0200337yin_parse_attribute(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, enum yin_argument arg_type,
Radek Krejcid6b76452019-09-03 17:03:03 +0200338 const char **arg_val, enum yang_arg val_type, enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200339{
David Sedlákc5b20842019-08-13 10:18:31 +0200340 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák8f7a1172019-06-20 14:42:18 +0200341 struct yin_arg_record *iter = NULL;
David Sedlák619db942019-07-03 14:47:30 +0200342 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200343
David Sedlák1bccdfa2019-06-17 15:55:27 +0200344 /* validation of attributes */
David Sedlák1f90d252019-07-10 17:09:32 +0200345 LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
David Sedlák00250342019-06-21 14:19:39 +0200346 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
347 if (!iter->prefix) {
David Sedlák060b00e2019-06-19 11:12:06 +0200348 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200349 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200350 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200351 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200352 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
David Sedlák292763b2019-07-09 11:10:53 +0200353 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200354 found = true;
David Sedlák4a650532019-07-10 11:55:18 +0200355 LY_CHECK_RET(yin_validate_value(ctx, val_type, iter->content, iter->content_len));
David Sedlák169cc522019-08-15 13:23:45 +0200356 INSERT_STRING(ctx->xml_ctx.ctx, *arg_val, iter->dynamic_content, iter->content, iter->content_len);
357 iter->dynamic_content = 0;
358 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200359 } else {
David Sedlák1538a842019-08-08 15:38:51 +0200360 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 +0200361 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200362 }
363 }
364 }
365
David Sedlák292763b2019-07-09 11:10:53 +0200366 /* anything else than Y_MAYBE_STR_ARG is mandatory */
367 if (val_type != Y_MAYBE_STR_ARG && !found) {
David Sedlák9c40a922019-07-08 17:04:43 +0200368 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 +0200369 return LY_EVALID;
370 }
371
372 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200373}
374
David Sedlákd6e56892019-07-01 15:40:24 +0200375/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200376 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200377 *
378 * @param[in] type Type of wanted record.
379 * @param[in] array_size Size of array.
380 * @param[in] array Searched array.
381 *
382 * @return Pointer to desired record on success, NULL if element is not in the array.
383 */
David Sedlákb4e44562019-07-04 15:42:12 +0200384static struct yin_subelement *
Radek Krejci12b1c152019-09-05 16:20:48 +0200385get_record(enum ly_stmt type, size_t array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200386{
Radek Krejci12b1c152019-09-05 16:20:48 +0200387 for (unsigned int u = 0; u < array_size; ++u) {
388 if (array[u].type == type) {
389 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200390 }
391 }
David Sedlákd6e56892019-07-01 15:40:24 +0200392 return NULL;
393}
394
David Sedlákbba38e52019-07-09 15:20:01 +0200395/**
396 * @brief Helper function to check mandatory constraint of subelement.
397 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200398 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200399 * @param[in] subelem_info Array of information about subelements.
400 * @param[in] subelem_info_size Size of subelem_info array.
401 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
402 *
403 * @return LY_ERR values.
404 */
405static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200406yin_check_subelem_mandatory_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200407 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200408{
David Sedlákb0faad82019-07-04 14:28:59 +0200409 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200410 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200411 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200412 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200413 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200414 return LY_EVALID;
415 }
416 }
417
418 return LY_SUCCESS;
419}
420
David Sedlákbba38e52019-07-09 15:20:01 +0200421/**
422 * @brief Helper function to check "first" constraint of subelement.
423 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200424 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200425 * @param[in] subelem_info Array of information about subelements.
426 * @param[in] subelem_info_size Size of subelem_info array.
427 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200428 * @param[in] exp_first Record in subelem_info array that is expected to be defined as first subelement, used for logging.
David Sedlákbba38e52019-07-09 15:20:01 +0200429 *
430 * @return LY_ERR values.
431 */
432static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200433yin_check_subelem_first_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200434 signed char subelem_info_size, enum ly_stmt current_element,
David Sedláke1a30302019-07-10 13:49:38 +0200435 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200436{
David Sedlákb0faad82019-07-04 14:28:59 +0200437 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200438 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200439 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
440 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200441 return LY_EVALID;
442 }
443 }
444
445 return LY_SUCCESS;
446}
447
David Sedlákbba38e52019-07-09 15:20:01 +0200448/**
David Sedlákb4e44562019-07-04 15:42:12 +0200449 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
450 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200451 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200452 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200453 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákd6e56892019-07-01 15:40:24 +0200454 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákb4e44562019-07-04 15:42:12 +0200455 * @param[in] kw Type of current element.
456 * @param[out] value Where value of attribute should be stored.
457 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200458 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200459 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200460 *
David Sedlákd6e56892019-07-01 15:40:24 +0200461 * @return LY_ERR values.
462 */
David Sedlákb4e44562019-07-04 15:42:12 +0200463static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200464yin_parse_simple_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt kw,
David Sedlákc5b20842019-08-13 10:18:31 +0200465 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 +0200466{
David Sedlák1f90d252019-07-10 17:09:32 +0200467 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200468 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200469 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200470 };
David Sedlákb4e44562019-07-04 15:42:12 +0200471
David Sedlákda8ffa32019-07-08 14:17:10 +0200472 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200473}
474
475/**
David Sedlák6542aed2019-08-14 10:47:43 +0200476 * @brief Parse path element.
477 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200478 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200479 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
480 * @param[in,out] data Data to read from, always moved to currently handled character.
481 * @param[in] kw Type of current element.
482 * @param[out] type Type structure to store parsed value, flags and extension instances.
483 *
484 * @return LY_ERR values.
485 */
486static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200487yin_parse_path(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt kw,
David Sedlák6542aed2019-08-14 10:47:43 +0200488 struct lysp_type *type)
489{
490 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
491 YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
492 type->flags |= LYS_SET_PATH;
493
494 return LY_SUCCESS;
495}
496
497/**
David Sedlákd3983112019-07-12 11:20:56 +0200498 * @brief Parse pattern element.
499 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200500 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd3983112019-07-12 11:20:56 +0200501 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
502 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200503 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200504 *
505 * @return LY_ERR values.
506 */
507static LY_ERR
508yin_parse_pattern(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
509 struct lysp_type *type)
510{
511 const char *real_value = NULL;
512 char *saved_value = NULL;
513 struct lysp_restr *restr;
514
515 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->patterns, restr, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200516 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &real_value, Y_STR_ARG, LY_STMT_PATTERN));
David Sedlákd3983112019-07-12 11:20:56 +0200517 size_t len = strlen(real_value);
518
519 saved_value = malloc(len + 2);
520 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
521 memmove(saved_value + 1, real_value, len);
522 FREE_STRING(ctx->xml_ctx.ctx, real_value);
523 saved_value[0] = 0x06;
524 saved_value[len + 1] = '\0';
525 restr->arg = lydict_insert_zc(ctx->xml_ctx.ctx, saved_value);
526 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
527 type->flags |= LYS_SET_PATTERN;
528
529 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200530 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
531 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
532 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
533 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
534 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
535 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákd3983112019-07-12 11:20:56 +0200536 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200537 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200538}
539
David Sedlákc5b20842019-08-13 10:18:31 +0200540/**
541 * @brief Parse fraction-digits element.
542 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200543 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200544 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
545 * @param[in,out] data Data to read from, always moved to currently handled character.
546 * @param[in,out] type Type structure to store value, flags and extension instances.
547 *
548 * @return LY_ERR values.
549 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200550static LY_ERR
551yin_parse_fracdigits(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
552 struct lysp_type *type)
553{
554 const char *temp_val = NULL;
555 char *ptr;
556 unsigned long int num;
557
Radek Krejcid6b76452019-09-03 17:03:03 +0200558 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_FRACTION_DIGITS));
David Sedlákf75d55e2019-07-12 16:52:50 +0200559
560 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200561 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200562 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
563 return LY_EVALID;
564 }
565
566 errno = 0;
567 num = strtoul(temp_val, &ptr, 10);
568 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200569 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200570 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
571 return LY_EVALID;
572 }
573 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200574 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200575 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
576 return LY_EVALID;
577 }
David Sedlák2ab5d8e2019-07-16 11:19:41 +0200578 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200579 type->fraction_digits = num;
580 type->flags |= LYS_SET_FRDIGITS;
581 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200582 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200583 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200584 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200585}
586
David Sedlák07869a52019-07-12 14:28:19 +0200587/**
David Sedlák43801c92019-08-05 15:58:54 +0200588 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200589 *
590 * @param[in,out] ctx YIN parser context for logging and to store current state.
591 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
592 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200593 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200594 *
595 * @return LY_ERR values.
596 */
David Sedlákca36c422019-07-12 12:47:55 +0200597static LY_ERR
David Sedlák43801c92019-08-05 15:58:54 +0200598yin_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 +0200599{
David Sedlák07869a52019-07-12 14:28:19 +0200600 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200601
David Sedlák43801c92019-08-05 15:58:54 +0200602 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->enums, en, LY_EMEM);
603 type->flags |= LYS_SET_ENUM;
David Sedláke6284fc2019-09-10 11:57:02 +0200604 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_STR_ARG, LY_STMT_ENUM));
David Sedlák43801c92019-08-05 15:58:54 +0200605 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
606 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
607 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200608
609 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200610 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
611 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
612 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
613 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
614 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
615 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákca36c422019-07-12 12:47:55 +0200616 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200617 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200618}
619
620/**
621 * @brief Parse bit element.
622 *
623 * @param[in,out] ctx YIN parser context for logging and to store current state.
624 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
625 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200626 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200627 *
628 * @return LY_ERR values.
629 */
630static LY_ERR
631yin_parse_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
632 struct lysp_type *type)
633{
634 struct lysp_type_enum *en;
635
636 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->bits, en, LY_EMEM);
637 type->flags |= LYS_SET_BIT;
Radek Krejcid6b76452019-09-03 17:03:03 +0200638 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, LY_STMT_BIT));
David Sedlák43801c92019-08-05 15:58:54 +0200639 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
640
641 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200642 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
643 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
644 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
645 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
646 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
647 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák43801c92019-08-05 15:58:54 +0200648 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200649 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200650}
651
David Sedlákd3983112019-07-12 11:20:56 +0200652/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200653 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
654 * more instances, such as base or if-feature.
655 *
656 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200657 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200658 * @param[in,out] data Data to read from, always moved to currently handled character.
659 * @param[in] kw Type of current element.
660 * @param[out] values Parsed values to add to.
661 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200662 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200663 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200664 *
665 * @return LY_ERR values.
666 */
667static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200668yin_parse_simple_elements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt kw,
David Sedlákc5b20842019-08-13 10:18:31 +0200669 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 +0200670{
671 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200672 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200673 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200674 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200675 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200676 };
677
David Sedlák1f90d252019-07-10 17:09:32 +0200678 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200679
680 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
681}
682
683/**
David Sedlák6542aed2019-08-14 10:47:43 +0200684 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
685 *
686 * @param[in,out] ctx YIN parser context for logging and to store current state.
687 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
688 * @param[in,out] data Data to read from, always moved to currently handled character.
689 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200690 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
David Sedlák6542aed2019-08-14 10:47:43 +0200691 * @param[in] arg_type Expected type of attribute.
692 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200693 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200694 *
695 * @return LY_ERR values.
696 */
697static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200698yin_parse_simple_elem(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt kw,
David Sedlák6542aed2019-08-14 10:47:43 +0200699 struct yin_subelement *subinfo, enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
700{
701 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
702 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subinfo->dest,
703 arg_type, arg_val_type, exts));
704 } else {
705 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subinfo->dest,
706 arg_type, arg_val_type, exts));
707 }
708
709 return LY_SUCCESS;
710}
711
712/**
713 * @brief Parse base element.
714 *
715 * @param[in,out] ctx YIN parser context for logging and to store current state.
716 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
717 * @param[in,out] data Data to read from, always moved to currently handled character.
718 * @param[in] parent Identification of parent element.
719 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200720 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200721 *
722 * @return LY_ERR values.
723 */
724static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200725yin_parse_base(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt parent,
David Sedlák6542aed2019-08-14 10:47:43 +0200726 void *dest, struct lysp_ext_instance **exts)
727{
728 struct lysp_type *type = NULL;
729
Radek Krejcid6b76452019-09-03 17:03:03 +0200730 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200731 type = (struct lysp_type *)dest;
Radek Krejcid6b76452019-09-03 17:03:03 +0200732 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
David Sedlák6542aed2019-08-14 10:47:43 +0200733 Y_PREF_IDENTIF_ARG, exts));
734 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200735 } else if (parent == LY_STMT_IDENTITY) {
736 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, LY_STMT_BASE, (const char ***)dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200737 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
738 } else {
739 LOGINT(ctx->xml_ctx.ctx);
740 return LY_EINT;
741 }
742
743 return LY_SUCCESS;
744}
745
746/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200747 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200748 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200749 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákcf5569a2019-07-11 13:31:34 +0200750 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
751 * @param[in,out] data Data to read from, always moved to currently handled character.
752 * @prama[out] type Type structure to store value, flag and extensions.
753 *
754 * @return LY_ERR values.
755 */
756static LY_ERR
757yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
758 const char **data, struct lysp_type *type)
759{
760 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200761 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200762 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200763 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200764
765 type->flags |= LYS_SET_REQINST;
Radek Krejcid6b76452019-09-03 17:03:03 +0200766 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_REQUIRE_INSTANCE));
David Sedlákcf5569a2019-07-11 13:31:34 +0200767 if (strcmp(temp_val, "true") == 0) {
768 type->require_instance = 1;
769 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200770 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
771 "require-instance", "true", "false");
David Sedlákcf5569a2019-07-11 13:31:34 +0200772 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
773 return LY_EVALID;
774 }
775 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
776
Radek Krejcid6b76452019-09-03 17:03:03 +0200777 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200778}
779
780/**
David Sedlákce77bf52019-07-11 16:59:31 +0200781 * @brief Parse modifier element.
782 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200783 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200784 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
785 * @param[in,out] data Data to read from, always moved to currently handled character.
786 * @param[in,out] pat Value to write to.
787 * @param[in,out] exts Extension instances to add to.
788 *
789 * @return LY_ERR values.
790 */
791static LY_ERR
792yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
793 const char **pat, struct lysp_ext_instance **exts)
794{
David Sedlákd3983112019-07-12 11:20:56 +0200795 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200796 const char *temp_val;
797 char *modified_val;
798 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200799 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákce77bf52019-07-11 16:59:31 +0200800 };
801
Radek Krejcid6b76452019-09-03 17:03:03 +0200802 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MODIFIER));
David Sedlákce77bf52019-07-11 16:59:31 +0200803 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200804 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
805 "modifier", "invert-match");
David Sedlákce77bf52019-07-11 16:59:31 +0200806 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
807 return LY_EVALID;
808 }
David Sedlákd3983112019-07-12 11:20:56 +0200809 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200810
811 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200812 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200813 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200814 strcpy(modified_val, *pat);
815 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200816
817 /* modify the new value */
818 modified_val[0] = 0x15;
819 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
820
Radek Krejcid6b76452019-09-03 17:03:03 +0200821 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200822}
823
824/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200825 * @brief Parse a restriction element (length, range or one instance of must).
826 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200827 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb7296dd2019-07-11 14:58:38 +0200828 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
829 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejcid6b76452019-09-03 17:03:03 +0200830 * @param[in] restr_kw Identificaton of element that is being parsed, can be set to LY_STMT_MUST, LY_STMT_LENGTH or LY_STMT_RANGE.
David Sedlák6542aed2019-08-14 10:47:43 +0200831 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200832 */
833static LY_ERR
834yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +0200835 enum ly_stmt restr_kw, struct lysp_restr *restr)
David Sedlákb7296dd2019-07-11 14:58:38 +0200836{
Radek Krejcid6b76452019-09-03 17:03:03 +0200837 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
David Sedlákb7296dd2019-07-11 14:58:38 +0200838 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200839 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
840 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
841 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
842 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
843 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200844 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200845 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200846 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200847 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
848
849 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
850}
851
852/**
David Sedlák6542aed2019-08-14 10:47:43 +0200853 * @brief Parse range element.
854 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200855 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200856 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
857 * @param[in,out] data Data to read from, always moved to currently handled character.
858 * @param[out] type Type structure to store parsed value and flags.
859 *
860 * @return LY_ERR values.
861 */
862static LY_ERR
863yin_parse_range(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
864 const char **data, struct lysp_type *type)
865{
866 type->range = calloc(1, sizeof *type->range);
867 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200868 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, LY_STMT_RANGE, type->range));
David Sedlák6542aed2019-08-14 10:47:43 +0200869 type->flags |= LYS_SET_RANGE;
870
871 return LY_SUCCESS;
872}
873
874/**
875 * @brief Parse length element.
876 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200877 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200878 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
879 * @param[in,out] data Data to read from, always moved to currently handled character.
880 * @param[out] type Type structure to store parsed value and flags.
881 *
882 * @return LY_ERR values.
883 */
884static LY_ERR
885yin_parse_length(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
886 const char **data, struct lysp_type *type)
887{
888 type->length = calloc(1, sizeof *type->length);
889 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200890 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200891 type->flags |= LYS_SET_LENGTH;
892
893 return LY_SUCCESS;
894}
895
896/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200897 * @brief Parse must element.
898 *
899 * @param[in,out] ctx YIN parser context for logging and to store current state.
900 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
901 * @param[in,out] data Data to read from, always moved to currently handled character.
902 * @param[in,out] restrs Restrictions to add to.
903 *
904 * @return LY_ERR values.
905 */
906static LY_ERR
907yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
908{
909 struct lysp_restr *restr;
910
911 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200912 return yin_parse_restriction(ctx, attrs, data, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200913}
914
915/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200916 * @brief Parse position or value element.
917 *
918 * @param[in,out] ctx YIN parser context for logging and to store current state.
919 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
920 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejcid6b76452019-09-03 17:03:03 +0200921 * @param[in] kw Type of current element, can be set to LY_STMT_POSITION or LY_STMT_VALUE.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200922 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200923 *
924 * @return LY_ERR values.
925 */
926static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +0200927yin_parse_value_pos(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +0200928 enum ly_stmt kw, struct lysp_type_enum *enm)
David Sedlák5545f5d2019-07-11 11:55:16 +0200929{
Radek Krejcid6b76452019-09-03 17:03:03 +0200930 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +0200931 const char *temp_val = NULL;
932 char *ptr;
933 long int num;
934 unsigned long int unum;
935
936 /* set value flag */
937 enm->flags |= LYS_SET_VALUE;
938
939 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200940 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 +0200941 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
Radek Krejcid6b76452019-09-03 17:03:03 +0200942 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200943 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 +0200944 goto error;
945 }
946
947 /* convert value */
948 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +0200949 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200950 num = strtol(temp_val, &ptr, 10);
951 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200952 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 +0200953 goto error;
954 }
955 } else {
956 unum = strtoul(temp_val, &ptr, 10);
957 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200958 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 +0200959 goto error;
960 }
961 }
962 /* check if whole argument value was converted */
963 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200964 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 +0200965 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200966 }
967 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +0200968 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 +0200969 goto error;
970 }
971 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +0200972 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200973 enm->value = num;
974 } else {
975 enm->value = unum;
976 }
977 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
978
979 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200980 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200981 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200982 };
David Sedlák5545f5d2019-07-11 11:55:16 +0200983 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
984
David Sedlákbf8a2b72019-08-14 16:48:10 +0200985error:
David Sedlák5545f5d2019-07-11 11:55:16 +0200986 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
987 return LY_EVALID;
988}
989
David Sedlák05404f62019-07-24 14:11:53 +0200990
991/**
992 * @brief Parse belongs-to element.
993 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200994 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +0200995 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
996 * @param[in,out] data Data to read from, always moved to currently handled character.
997 * @param[out] submod Structure of submodule that is being parsed.
998 * @param[in,out] exts Extension instances to add to.
999 *
1000 * @return LY_ERR values
1001 */
1002static LY_ERR
1003yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1004 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
1005{
1006 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001007 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1008 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák05404f62019-07-24 14:11:53 +02001009 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001010 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
David Sedlák05404f62019-07-24 14:11:53 +02001011
Radek Krejcid6b76452019-09-03 17:03:03 +02001012 return yin_parse_content(ctx, subelems, 2, data, LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001013}
1014
David Sedlák5545f5d2019-07-11 11:55:16 +02001015/**
David Sedlákc1771b12019-07-10 15:55:46 +02001016 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001017 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001018 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001019 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001020 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákcf5569a2019-07-11 13:31:34 +02001021 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejcid6b76452019-09-03 17:03:03 +02001022 * @param[in] elem_type Type of element can be set to LY_STMT_ORGANIZATION or LY_STMT_CONTACT or LY_STMT_DESCRIPTION or LY_STMT_REFERENCE.
David Sedlákb4e44562019-07-04 15:42:12 +02001023 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001024 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001025 *
1026 * @return LY_ERR values.
1027 */
1028static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001029yin_parse_meta(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001030 enum ly_stmt elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +02001031{
Radek Krejcid6b76452019-09-03 17:03:03 +02001032 assert(elem_type == LY_STMT_ORGANIZATION || elem_type == LY_STMT_CONTACT || elem_type == LY_STMT_DESCRIPTION || elem_type == LY_STMT_REFERENCE);
David Sedlákb4e44562019-07-04 15:42:12 +02001033
David Sedlák968ac342019-07-11 15:17:59 +02001034 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001035 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1036 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +02001037 };
David Sedlákdf2a9732019-08-07 13:23:16 +02001038 /* check attributes */
1039 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 +02001040
David Sedlákdf2a9732019-08-07 13:23:16 +02001041 /* parse content */
David Sedlákda8ffa32019-07-08 14:17:10 +02001042 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001043}
1044
1045/**
David Sedlákc1771b12019-07-10 15:55:46 +02001046 * @brief Parse error-message element.
1047 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001048 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001049 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákc1771b12019-07-10 15:55:46 +02001050 * @param[in,out] data Data to read from.
1051 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001052 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001053 *
1054 * @return LY_ERR values.
1055 */
1056static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001057yin_parse_err_msg(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdf2a9732019-08-07 13:23:16 +02001058 const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +02001059{
David Sedlák968ac342019-07-11 15:17:59 +02001060 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001061 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1062 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +02001063 };
David Sedlákc1771b12019-07-10 15:55:46 +02001064
David Sedlákdf2a9732019-08-07 13:23:16 +02001065 /* check attributes */
David Sedlák071f7662019-09-12 02:02:51 +02001066 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, LY_STMT_ERROR_MESSAGE));
David Sedlákdf2a9732019-08-07 13:23:16 +02001067
Radek Krejcid6b76452019-09-03 17:03:03 +02001068 return yin_parse_content(ctx, subelems, 2, data, LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001069}
1070
1071/**
David Sedlák6542aed2019-08-14 10:47:43 +02001072 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001073 *
1074 * @param[in,out] ctx YIN parser context for logging and to store current state.
1075 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1076 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák6542aed2019-08-14 10:47:43 +02001077 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001078 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001079 *
1080 * @return LY_ERR values.
1081 */
1082static LY_ERR
David Sedlák6542aed2019-08-14 10:47:43 +02001083yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001084 enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001085{
David Sedlák6542aed2019-08-14 10:47:43 +02001086 struct lysp_type *type = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +02001087 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001088 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
1089 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1090 type = *((struct lysp_type **)subinfo->dest);
1091 } else {
1092 type = (struct lysp_type *)subinfo->dest;
1093 }
1094 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001095 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001096 struct lysp_type *nested_type = NULL;
1097 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->types, nested_type, LY_EMEM);
1098 type->flags |= LYS_SET_TYPE;
1099 type = nested_type;
1100 }
David Sedlák374d2b32019-07-17 15:06:55 +02001101 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001102 {LY_STMT_BASE, type, 0},
1103 {LY_STMT_BIT, type, 0},
1104 {LY_STMT_ENUM, type, 0},
1105 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1106 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1107 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1108 {LY_STMT_PATTERN, type, 0},
1109 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1110 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1111 {LY_STMT_TYPE, type},
1112 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák374d2b32019-07-17 15:06:55 +02001113 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001114 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1115 return yin_parse_content(ctx, subelems, 11, data, LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001116}
1117
David Sedlák1af868e2019-07-17 17:03:14 +02001118/**
1119 * @brief Parse max-elements element.
1120 *
1121 * @param[in,out] ctx YIN parser context for logging and to store current state.
1122 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1123 * @param[in,out] data Data to read from, always moved to currently handled character.
1124 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001125 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001126 * @param[in,out] exts Extension instances to add to.
1127 *
1128 * @return LY_ERR values.
1129 */
1130static LY_ERR
1131yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
1132 uint16_t *flags, struct lysp_ext_instance **exts)
1133{
1134 const char *temp_val = NULL;
1135 char *ptr;
1136 unsigned long int num;
1137 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001138 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák1af868e2019-07-17 17:03:14 +02001139 };
David Sedlák374d2b32019-07-17 15:06:55 +02001140
David Sedlák1af868e2019-07-17 17:03:14 +02001141 *flags |= LYS_SET_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02001142 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MAX_ELEMENTS));
David Sedlák1af868e2019-07-17 17:03:14 +02001143 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 +02001144 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001145 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1146 return LY_EVALID;
1147 }
1148
1149 if (strcmp(temp_val, "unbounded")) {
1150 errno = 0;
1151 num = strtoul(temp_val, &ptr, 10);
1152 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001153 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001154 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1155 return LY_EVALID;
1156 }
1157 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001158 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001159 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1160 return LY_EVALID;
1161 }
1162 *max = num;
1163 }
1164 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
Radek Krejcid6b76452019-09-03 17:03:03 +02001165 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001166}
David Sedlák374d2b32019-07-17 15:06:55 +02001167
1168/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001169 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001170 *
1171 * @param[in,out] ctx YIN parser context for logging and to store current state.
1172 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1173 * @param[in,out] data Data to read from, always moved to currently handled character.
1174 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001175 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001176 * @param[in,out] exts Extension instances to add to.
1177 *
1178 * @return LY_ERR values.
1179 */
1180static LY_ERR
1181yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
1182 uint16_t *flags, struct lysp_ext_instance **exts)
1183{
1184 const char *temp_val = NULL;
1185 char *ptr;
1186 unsigned long int num;
1187 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001188 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák09e18c92019-07-18 11:17:11 +02001189 };
1190
1191 *flags |= LYS_SET_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02001192 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MIN_ELEMENTS));
David Sedlák09e18c92019-07-18 11:17:11 +02001193
1194 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001195 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001196 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1197 return LY_EVALID;
1198 }
1199
1200 errno = 0;
1201 num = strtoul(temp_val, &ptr, 10);
1202 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001203 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001204 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1205 return LY_EVALID;
1206 }
1207 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001208 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001209 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1210 return LY_EVALID;
1211 }
1212 *min = num;
1213 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
Radek Krejcid6b76452019-09-03 17:03:03 +02001214 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001215}
1216
David Sedláka2dad212019-07-18 12:45:19 +02001217/**
1218 * @brief Parse min-elements or max-elements element.
1219 *
1220 * @param[in,out] ctx YIN parser context for logging and to store current state.
1221 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1222 * @param[in,out] data Data to read from, always moved to currently handled character.
1223 * @param[in] parent Identification of parent element.
1224 * @param[in] current Identification of current element.
1225 * @param[in] dest Where the parsed value and flags should be stored.
1226 *
1227 * @return LY_ERR values.
1228 */
David Sedlák09e18c92019-07-18 11:17:11 +02001229static LY_ERR
1230yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001231 enum ly_stmt parent, enum ly_stmt current, void *dest)
David Sedlák09e18c92019-07-18 11:17:11 +02001232{
Radek Krejcid6b76452019-09-03 17:03:03 +02001233 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1234 assert(parent == LY_STMT_LEAF_LIST || parent == LY_STMT_REFINE || parent == LY_STMT_LIST || parent == LY_STMT_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001235 uint32_t *lim;
1236 uint16_t *flags;
1237 struct lysp_ext_instance **exts;
1238
Radek Krejcid6b76452019-09-03 17:03:03 +02001239 if (parent == LY_STMT_LEAF_LIST) {
1240 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001241 flags = &((struct lysp_node_leaflist *)dest)->flags;
1242 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001243 } else if (parent == LY_STMT_REFINE) {
1244 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001245 flags = &((struct lysp_refine *)dest)->flags;
1246 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001247 } else if (parent == LY_STMT_LIST) {
1248 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001249 flags = &((struct lysp_node_list *)dest)->flags;
1250 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001251 } else {
1252 lim = ((struct minmax_dev_meta *)dest)->lim;
1253 flags = ((struct minmax_dev_meta *)dest)->flags;
1254 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001255 }
1256
Radek Krejcid6b76452019-09-03 17:03:03 +02001257 if (current == LY_STMT_MAX_ELEMENTS) {
David Sedlák09e18c92019-07-18 11:17:11 +02001258 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1259 } else {
1260 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1261 }
1262
1263 return LY_SUCCESS;
1264}
1265
1266/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001267 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001268 *
1269 * @param[in,out] ctx YIN parser context for logging and to store current state.
1270 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1271 * @param[in,out] data Data to read from, always moved to currently handled character.
1272 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001273 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001274 *
1275 * @return LY_ERR values.
1276 */
1277static LY_ERR
1278yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1279 uint16_t *flags, struct lysp_ext_instance **exts)
1280{
1281 const char *temp_val;
1282 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001283 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedláka2dad212019-07-18 12:45:19 +02001284 };
1285
Radek Krejcid6b76452019-09-03 17:03:03 +02001286 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_ORDERED_BY));
David Sedláka2dad212019-07-18 12:45:19 +02001287 if (strcmp(temp_val, "system") == 0) {
1288 *flags |= LYS_ORDBY_SYSTEM;
1289 } else if (strcmp(temp_val, "user") == 0) {
1290 *flags |= LYS_ORDBY_USER;
1291 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001292 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1293 "ordered-by", "system", "user");
David Sedláka2dad212019-07-18 12:45:19 +02001294 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1295 return LY_EVALID;
1296 }
1297 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1298
Radek Krejcid6b76452019-09-03 17:03:03 +02001299 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001300}
1301
1302/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001303 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001304 *
1305 * @param[in,out] ctx YIN parser context for logging and to store current state.
1306 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1307 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejcid6b76452019-09-03 17:03:03 +02001308 * @param[in] any_kw Identification of current element, can be set to LY_STMT_ANYDATA or LY_STMT_ANYXML
David Sedlákad83cf92019-08-13 12:53:53 +02001309 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001310 *
1311 * @return LY_ERR values.
1312 */
1313static LY_ERR
1314yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001315 enum ly_stmt any_kw, struct tree_node_meta *node_meta)
David Sedlák8a83bbb2019-07-18 14:46:00 +02001316{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001317 struct lysp_node_anydata *any;
1318
David Sedlák8d552d62019-08-06 15:29:05 +02001319 /* create new sibling */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02001320 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001321 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001322 any->parent = node_meta->parent;
1323
David Sedlákbf8a2b72019-08-14 16:48:10 +02001324 /* parse argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001325 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 +02001326
1327 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001328 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1329 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1330 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1331 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1332 {LY_STMT_MUST, &any->musts, 0},
1333 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1334 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1335 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1336 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8a83bbb2019-07-18 14:46:00 +02001337 };
1338 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1339}
1340
1341/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001342 * @brief parse leaf element.
1343 *
1344 * @param[in,out] ctx YIN parser context for logging and to store current state.
1345 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1346 * @param[in,out] data Data to read from, always moved to currently handled character.
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ák203ca3a2019-07-18 15:26:25 +02001348 *
1349 * @return LY_ERR values.
1350 */
1351static LY_ERR
1352yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1353 struct tree_node_meta *node_meta)
1354{
David Sedlák203ca3a2019-07-18 15:26:25 +02001355 struct lysp_node_leaf *leaf;
1356
David Sedlák8d552d62019-08-06 15:29:05 +02001357 /* create structure new leaf */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02001358 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001359 leaf->nodetype = LYS_LEAF;
1360 leaf->parent = node_meta->parent;
1361
David Sedlák203ca3a2019-07-18 15:26:25 +02001362 /* parser argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001363 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, LY_STMT_LEAF));
David Sedlák203ca3a2019-07-18 15:26:25 +02001364
1365 /* parse content */
1366 struct yin_subelement subelems[12] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001367 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1368 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1369 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1370 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1371 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1372 {LY_STMT_MUST, &leaf->musts, 0},
1373 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1374 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1375 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1376 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1377 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1378 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001379 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001380 return yin_parse_content(ctx, subelems, 12, data, LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001381}
1382
1383/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001384 * @brief Parse leaf-list element.
1385 *
1386 * @param[in,out] ctx YIN parser context for logging and to store current state.
1387 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1388 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001389 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001390 *
1391 * @return LY_ERR values.
1392 */
1393static LY_ERR
1394yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1395 struct tree_node_meta *node_meta)
1396{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001397 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001398
David Sedlákb9eeb9c2019-09-13 11:17:19 +02001399 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001400
David Sedlákc3da3ef2019-07-19 12:56:08 +02001401 llist->nodetype = LYS_LEAFLIST;
1402 llist->parent = node_meta->parent;
1403
David Sedlákc3da3ef2019-07-19 12:56:08 +02001404 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001405 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, LY_STMT_LEAF_LIST));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001406
1407 /* parse content */
1408 struct yin_subelement subelems[14] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001409 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1410 {LY_STMT_DEFAULT, &llist->dflts, 0},
1411 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1412 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1413 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1414 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1415 {LY_STMT_MUST, &llist->musts, 0},
1416 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1417 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1418 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1419 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1420 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1421 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1422 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001423 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001424 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001425
David Sedlákbf8a2b72019-08-14 16:48:10 +02001426 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001427 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001428 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001429 return LY_EVALID;
1430 }
1431 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001432 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001433 return LY_EVALID;
1434 }
1435
1436 return LY_SUCCESS;
1437}
1438
1439/**
David Sedlák04e17b22019-07-19 15:29:48 +02001440 * @brief Parse typedef element.
1441 *
1442 * @param[in,out] ctx YIN parser context for logging and to store current state.
1443 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1444 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001445 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001446 *
1447 * @return LY_ERR values.
1448 */
1449static LY_ERR
1450yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02001451 struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001452{
1453 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001454 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
David Sedlák6881b512019-08-13 12:52:00 +02001455 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001456
1457 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001458 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, LY_STMT_TYPEDEF));
David Sedlák04e17b22019-07-19 15:29:48 +02001459
1460 /* parse content */
1461 struct yin_subelement subelems[7] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001462 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1463 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1464 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1465 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1466 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1467 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1468 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001469 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001470 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001471
1472 /* store data for collision check */
1473 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
David Sedláke8b74df2019-08-14 14:18:22 +02001474 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0) == -1, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001475 }
1476
1477 return LY_SUCCESS;
1478}
1479
1480/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001481 * @brief Parse refine element.
1482 *
1483 * @param[in,out] ctx YIN parser context for logging and to store current state.
1484 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1485 * @param[in,out] data Data to read from, always moved to currently handled character.
1486 * @param[in,out] refines Refines to add to.
1487 *
1488 * @return LY_ERR values.
1489 */
1490static LY_ERR
1491yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1492 struct lysp_refine **refines)
1493{
1494 struct lysp_refine *rf;
1495
1496 /* allocate new refine */
1497 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1498
1499 /* parse attribute */
Radek Krejcid6b76452019-09-03 17:03:03 +02001500 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
David Sedlákd2d676a2019-07-22 11:28:19 +02001501 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1502
1503 /* parse content */
1504 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001505 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1506 {LY_STMT_DEFAULT, &rf->dflts, 0},
1507 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1508 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
1509 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1510 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1511 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1512 {LY_STMT_MUST, &rf->musts, 0},
1513 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1514 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1515 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001516 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001517 return yin_parse_content(ctx, subelems, 11, data, LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001518}
1519
1520/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001521 * @brief Parse uses element.
1522 *
1523 * @param[in,out] ctx YIN parser context for logging and to store current state.
1524 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1525 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001526 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001527 *
1528 * @return LY_ERR values.
1529 */
1530static LY_ERR
1531yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1532 struct tree_node_meta *node_meta)
1533{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001534 struct lysp_node_uses *uses;
1535
David Sedlák8d552d62019-08-06 15:29:05 +02001536 /* create new uses */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02001537 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001538 uses->nodetype = LYS_USES;
1539 uses->parent = node_meta->parent;
1540
David Sedlák0d6de5a2019-07-22 13:25:44 +02001541 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001542 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, LY_STMT_USES));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001543
1544 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001545 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001546 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001547 {LY_STMT_AUGMENT, &augments, 0},
1548 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1549 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1550 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1551 {LY_STMT_REFINE, &uses->refines, 0},
1552 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1553 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1554 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001555 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001556 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001557 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1558
1559 return LY_SUCCESS;
1560}
1561
1562/**
David Sedlákaa854b02019-07-22 14:17:10 +02001563 * @brief Parse revision element.
1564 *
1565 * @param[in,out] ctx YIN parser context for logging and to store current state.
1566 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1567 * @param[in,out] data Data to read from, always moved to currently handled character.
1568 * @param[in,out] revs Parsed revisions to add to.
1569 *
1570 * @return LY_ERR values.
1571 */
1572static LY_ERR
1573yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1574 struct lysp_revision **revs)
1575{
1576 struct lysp_revision *rev;
1577 const char *temp_date = NULL;
1578
1579 /* allocate new reivison */
1580 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1581
1582 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001583 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, LY_STMT_REVISION));
David Sedlákaa854b02019-07-22 14:17:10 +02001584 /* check value */
1585 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1586 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1587 return LY_EVALID;
1588 }
1589 strcpy(rev->date, temp_date);
1590 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1591
1592 /* parse content */
1593 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001594 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1595 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1596 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001597 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001598 return yin_parse_content(ctx, subelems, 3, data, LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001599}
1600
David Sedlák5e13dea2019-07-22 16:06:45 +02001601/**
1602 * @brief Parse include element.
1603 *
1604 * @param[in,out] ctx YIN parser context for logging and to store current state.
1605 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1606 * @param[in,out] data Data to read from, always moved to currently handled character.
1607 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1608 *
1609 * @return LY_ERR values.
1610 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001611static LY_ERR
1612yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1613 struct include_meta *inc_meta)
1614{
1615 struct lysp_include *inc;
1616
1617 /* allocate new include */
1618 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1619
1620 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001621 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, LY_STMT_INCLUDE));
David Sedlák0c2bab92019-07-22 15:33:19 +02001622
1623 /* submodules share the namespace with the module names, so there must not be
1624 * a module of the same name in the context, no need for revision matching */
1625 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 +02001626 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001627 return LY_EVALID;
1628 }
1629
1630 /* parse content */
1631 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001632 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1633 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1634 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1635 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák0c2bab92019-07-22 15:33:19 +02001636 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001637 return yin_parse_content(ctx, subelems, 4, data, LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001638}
1639
David Sedlákaa854b02019-07-22 14:17:10 +02001640/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001641 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001642 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001643 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001644 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of revision-date element.
1645 * @param[in,out] data Data to read from, always moved to currently handled character.
1646 * @param[in,out] rev Array to store the parsed value in.
1647 * @param[in,out] exts Extension instances to add to.
1648 *
1649 * @return LY_ERR values.
1650 */
1651static LY_ERR
1652yin_parse_revision_date(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, char *rev,
1653 struct lysp_ext_instance **exts)
1654{
1655 const char *temp_rev;
1656 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001657 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001658 };
1659
Radek Krejcid6b76452019-09-03 17:03:03 +02001660 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, LY_STMT_REVISION_DATE));
David Sedlákdfbbb442019-08-06 16:33:21 +02001661 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
1662 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
1663
1664 strcpy(rev, temp_rev);
1665 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
1666
Radek Krejcid6b76452019-09-03 17:03:03 +02001667 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001668}
1669
1670/**
1671 * @brief Parse config element.
1672 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001673 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001674 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1675 * @param[in,out] data Data to read from, always moved to currently handled character.
1676 * @param[in,out] flags Flags to add to.
1677 * @param[in,out] exts Extension instances to add to.
1678 *
1679 * @return LY_ERR values.
1680 */
1681static LY_ERR
1682yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1683 struct lysp_ext_instance **exts)
1684{
1685 const char *temp_val = NULL;
1686 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001687 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001688 };
1689
Radek Krejcid6b76452019-09-03 17:03:03 +02001690 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_CONFIG));
David Sedlákdfbbb442019-08-06 16:33:21 +02001691 if (strcmp(temp_val, "true") == 0) {
1692 *flags |= LYS_CONFIG_W;
1693 } else if (strcmp(temp_val, "false") == 0) {
1694 *flags |= LYS_CONFIG_R;
1695 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001696 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
1697 "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001698 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1699 return LY_EVALID;
1700 }
1701 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1702
Radek Krejcid6b76452019-09-03 17:03:03 +02001703 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001704}
1705
1706/**
1707 * @brief Parse yang-version element.
1708 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001709 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001710 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yang-version element.
1711 * @param[in] data Data to read from, always moved to currently handled character.
1712 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001713 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001714 *
1715 * @return LY_ERR values.
1716 */
1717static LY_ERR
1718yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
1719 struct lysp_ext_instance **exts)
1720{
1721 const char *temp_version = NULL;
1722 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001723 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001724 };
1725
Radek Krejcid6b76452019-09-03 17:03:03 +02001726 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, LY_STMT_YANG_VERSION));
David Sedlákdfbbb442019-08-06 16:33:21 +02001727 if (strcmp(temp_version, "1.0") == 0) {
1728 *version = LYS_VERSION_1_0;
1729 } else if (strcmp(temp_version, "1.1") == 0) {
1730 *version = LYS_VERSION_1_1;
1731 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001732 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
1733 "yang-version", "1.0", "1.1");
David Sedlákdfbbb442019-08-06 16:33:21 +02001734 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1735 return LY_EVALID;
1736 }
1737 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1738 ctx->mod_version = *version;
1739
Radek Krejcid6b76452019-09-03 17:03:03 +02001740 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001741}
1742
1743/**
1744 * @brief Parse import element.
1745 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001746 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001747 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1748 * @param[in,out] data Data to read from, always moved to currently handled character.
1749 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1750 *
1751 * @return LY_ERR values.
1752 */
1753static LY_ERR
1754yin_parse_import(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct import_meta *imp_meta)
1755{
1756 struct lysp_import *imp;
1757 /* allocate new element in sized array for import */
1758 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
1759
1760 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001761 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1762 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1763 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1764 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1765 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001766 };
1767
1768 /* parse import attributes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001769 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
1770 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001771 /* check prefix validity */
1772 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1773
1774 return LY_SUCCESS;
1775}
1776
1777/**
1778 * @brief Parse mandatory element.
1779 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001780 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001781 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1782 * @param[in,out] data Data to read from, always moved to currently handled character.
1783 * @param[in,out] flags Flags to add to.
1784 * @param[in,out] exts Extension instances to add to.
1785 *
1786 * @return LY_ERR values.
1787 */
1788static LY_ERR
1789yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1790 struct lysp_ext_instance **exts)
1791{
1792 const char *temp_val = NULL;
1793 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001794 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001795 };
1796
Radek Krejcid6b76452019-09-03 17:03:03 +02001797 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MANDATORY));
David Sedlákdfbbb442019-08-06 16:33:21 +02001798 if (strcmp(temp_val, "true") == 0) {
1799 *flags |= LYS_MAND_TRUE;
1800 } else if (strcmp(temp_val, "false") == 0) {
1801 *flags |= LYS_MAND_FALSE;
1802 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001803 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1804 "mandatory", "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001805 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1806 return LY_EVALID;
1807 }
1808 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1809
Radek Krejcid6b76452019-09-03 17:03:03 +02001810 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001811}
1812
1813/**
1814 * @brief Parse status element.
1815 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001816 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001817 * @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_status(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 *value = NULL;
1829 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001830 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001831 };
1832
Radek Krejcid6b76452019-09-03 17:03:03 +02001833 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &value, Y_STR_ARG, LY_STMT_STATUS));
David Sedlákdfbbb442019-08-06 16:33:21 +02001834 if (strcmp(value, "current") == 0) {
1835 *flags |= LYS_STATUS_CURR;
1836 } else if (strcmp(value, "deprecated") == 0) {
1837 *flags |= LYS_STATUS_DEPRC;
1838 } else if (strcmp(value, "obsolete") == 0) {
1839 *flags |= LYS_STATUS_OBSLT;
1840 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001841 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
1842 "status", "current", "deprecated", "obsolete");
David Sedlákdfbbb442019-08-06 16:33:21 +02001843 FREE_STRING(ctx->xml_ctx.ctx, value);
1844 return LY_EVALID;
1845 }
1846 FREE_STRING(ctx->xml_ctx.ctx, value);
1847
Radek Krejcid6b76452019-09-03 17:03:03 +02001848 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001849}
1850
1851/**
1852 * @brief Parse when element.
1853 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001854 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001855 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of when element.
1856 * @param[in,out] data Data to read from, always moved to currently handled character.
1857 * @param[out] when_p When pointer to parse to.
1858 */
1859static LY_ERR
1860yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
1861{
1862 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001863 LY_ERR ret = LY_SUCCESS;
1864
David Sedlákdfbbb442019-08-06 16:33:21 +02001865 when = calloc(1, sizeof *when);
1866 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001867 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001868 LY_CHECK_ERR_RET(ret, free(when), ret);
1869
David Sedlákdfbbb442019-08-06 16:33:21 +02001870 *when_p = when;
1871 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001872 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1873 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1874 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001875 };
1876
Radek Krejcid6b76452019-09-03 17:03:03 +02001877 return yin_parse_content(ctx, subelems, 3, data, LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001878}
1879
1880/**
1881 * @brief Parse yin-elemenet element.
1882 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001883 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001884 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yin-element element.
1885 * @param[in,out] data Data to read from, always moved to currently handled position.
1886 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001887 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001888 *
1889 * @return LY_ERR values.
1890 */
1891static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001892yin_parse_yin_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdfbbb442019-08-06 16:33:21 +02001893 uint16_t *flags, struct lysp_ext_instance **exts)
1894{
1895 const char *temp_val = NULL;
1896 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001897 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001898 };
1899
Radek Krejcid6b76452019-09-03 17:03:03 +02001900 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_YIN_ELEMENT));
David Sedlákdfbbb442019-08-06 16:33:21 +02001901 if (strcmp(temp_val, "true") == 0) {
1902 *flags |= LYS_YINELEM_TRUE;
1903 } else if (strcmp(temp_val, "false") == 0) {
1904 *flags |= LYS_YINELEM_FALSE;
1905 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001906 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1907 "yin-element", "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001908 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1909 return LY_EVALID;
1910 }
1911 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1912
Radek Krejcid6b76452019-09-03 17:03:03 +02001913 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001914}
1915
1916/**
1917 * @brief Parse argument element.
1918 *
1919 * @param[in,out] xml_ctx Xml context.
1920 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of argument element.
1921 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001922 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1923 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001924 *
1925 * @return LY_ERR values.
1926 */
1927static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001928yin_parse_argument(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdfbbb442019-08-06 16:33:21 +02001929 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
1930{
1931 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001932 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1933 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001934 };
1935
Radek Krejcid6b76452019-09-03 17:03:03 +02001936 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, LY_STMT_ARGUMENT));
David Sedlákdfbbb442019-08-06 16:33:21 +02001937
Radek Krejcid6b76452019-09-03 17:03:03 +02001938 return yin_parse_content(ctx, subelems, 2, data, LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001939}
1940
1941/**
1942 * @brief Parse the extension statement.
1943 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001944 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001945 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension element.
1946 * @param[in,out] data Data to read from.
1947 * @param[in,out] extensions Extensions to add to.
1948 *
1949 * @return LY_ERR values.
1950 */
1951static LY_ERR
1952yin_parse_extension(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_ext **extensions)
1953{
1954 struct lysp_ext *ex;
1955 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001956 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ex->name, Y_IDENTIF_ARG, LY_STMT_EXTENSION));
David Sedlákdfbbb442019-08-06 16:33:21 +02001957
1958 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1959 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001960 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1961 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1962 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1963 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1964 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001965 };
1966
Radek Krejcid6b76452019-09-03 17:03:03 +02001967 return yin_parse_content(ctx, subelems, 5, data, LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001968}
1969
1970/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001971 * @brief Parse feature element.
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 current element.
1975 * @param[in,out] data Data to read from, always moved to currently handled character.
1976 * @param[in,out] features Features to add to.
1977 *
1978 * @return LY_ERR values.
1979 */
1980static LY_ERR
1981yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1982 struct lysp_feature **features)
1983{
1984 struct lysp_feature *feat;
1985
1986 /* allocate new feature */
1987 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
1988
1989 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001990 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, LY_STMT_FEATURE));
David Sedlák5e13dea2019-07-22 16:06:45 +02001991
1992 /* parse content */
1993 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001994 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1995 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
1996 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1997 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1998 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák5e13dea2019-07-22 16:06:45 +02001999 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002000 return yin_parse_content(ctx, subelems, 5, data, LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02002001}
2002
2003/**
David Sedlák28794f22019-07-22 16:45:00 +02002004 * @brief Parse identity element.
2005 *
2006 * @param[in,out] ctx YIN parser context for logging and to store current state.
2007 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2008 * @param[in,out] data Data to read from, always moved to currently handled character.
2009 * @param[in,out] identities Identities to add to.
2010 *
2011 * @return LY_ERR values.
2012 */
2013static LY_ERR
2014yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2015 struct lysp_ident **identities)
2016{
2017 struct lysp_ident *ident;
2018
2019 /* allocate new identity */
2020 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
2021
2022 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002023 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, LY_STMT_IDENTITY));
David Sedlák28794f22019-07-22 16:45:00 +02002024
2025 /* parse content */
2026 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002027 {LY_STMT_BASE, &ident->bases, 0},
2028 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2029 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2030 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2031 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2032 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák28794f22019-07-22 16:45:00 +02002033 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002034 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002035}
2036
2037/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002038 * @brief Parse list element.
2039 *
2040 * @param[in,out] ctx YIN parser context for logging and to store current state.
2041 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2042 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002043 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002044 *
2045 * @return LY_ERR values.
2046 */
2047static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02002048yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2049 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002050{
David Sedlákaf536aa2019-07-23 13:42:23 +02002051 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002052 LY_ERR ret = LY_SUCCESS;
2053 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02002054
David Sedlákb9eeb9c2019-09-13 11:17:19 +02002055 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002056 list->nodetype = LYS_LIST;
2057 list->parent = node_meta->parent;
2058
David Sedlákaf536aa2019-07-23 13:42:23 +02002059 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002060 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, LY_STMT_LIST));
David Sedlákaf536aa2019-07-23 13:42:23 +02002061
2062 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02002063 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002064 LY_STMT_ACTION, &list->actions, 0,
2065 LY_STMT_ANYDATA, &list->child, 0,
2066 LY_STMT_ANYXML, &list->child, 0,
2067 LY_STMT_CHOICE, &list->child, 0,
2068 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2069 LY_STMT_CONTAINER, &list->child, 0,
2070 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2071 LY_STMT_GROUPING, &list->groupings, 0,
2072 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2073 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2074 LY_STMT_LEAF, &list->child, 0,
2075 LY_STMT_LEAF_LIST, &list->child, 0,
2076 LY_STMT_LIST, &list->child, 0,
2077 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2078 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2079 LY_STMT_MUST, &list->musts, 0,
2080 LY_STMT_NOTIFICATION, &list->notifs, 0,
2081 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2082 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2083 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2084 LY_STMT_TYPEDEF, &list->typedefs, 0,
2085 LY_STMT_UNIQUE, &list->uniques, 0,
2086 LY_STMT_USES, &list->child, 0,
2087 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2088 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002089 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002090 ret = yin_parse_content(ctx, subelems, 25, data, LY_STMT_LIST, NULL, &list->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002091 subelems_deallocator(25, subelems);
2092 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002093
2094 /* finalize parent pointers to the reallocated items */
2095 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
2096
2097 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02002098 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002099 return LY_EVALID;
2100 }
2101
2102 return LY_SUCCESS;
2103}
2104
2105/**
David Sedlák031b9e72019-07-23 15:19:37 +02002106 * @brief Parse notification element.
2107 *
2108 * @param[in,out] ctx YIN parser context for logging and to store current state.
2109 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2110 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02002111 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002112 *
2113 * @return LY_ERR values.
2114 */
2115static LY_ERR
2116yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002117 struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002118{
2119 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002120 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002121 LY_ERR ret = LY_SUCCESS;
2122 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002123
2124 /* allocate new notification */
David Sedlák6881b512019-08-13 12:52:00 +02002125 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002126 notif->nodetype = LYS_NOTIF;
2127 notif->parent = notif_meta->parent;
2128
2129 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002130 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, LY_STMT_NOTIFICATION));
David Sedlák031b9e72019-07-23 15:19:37 +02002131
2132 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002133 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002134 LY_STMT_ANYDATA, &notif->data, 0,
2135 LY_STMT_ANYXML, &notif->data, 0,
2136 LY_STMT_CHOICE, &notif->data, 0,
2137 LY_STMT_CONTAINER, &notif->data, 0,
2138 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2139 LY_STMT_GROUPING, &notif->groupings, 0,
2140 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2141 LY_STMT_LEAF, &notif->data, 0,
2142 LY_STMT_LEAF_LIST, &notif->data, 0,
2143 LY_STMT_LIST, &notif->data, 0,
2144 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2145 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2146 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2147 LY_STMT_TYPEDEF, &notif->typedefs, 0,
2148 LY_STMT_USES, &notif->data, 0,
2149 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002150 ));
2151
Radek Krejcid6b76452019-09-03 17:03:03 +02002152 ret = yin_parse_content(ctx, subelems, 16, data, LY_STMT_NOTIFICATION, NULL, &notif->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002153 subelems_deallocator(16, subelems);
2154 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002155
2156 /* finalize parent pointers to the reallocated items */
2157 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2158
2159 return LY_SUCCESS;
2160}
2161
2162/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002163 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002164 *
2165 * @param[in,out] ctx YIN parser context for logging and to store current state.
2166 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2167 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002168 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002169 *
2170 * @return LY_ERR values.
2171 */
2172static LY_ERR
2173yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002174 struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002175{
2176 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002177 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002178 LY_ERR ret = LY_SUCCESS;
2179 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002180
2181 /* create new grouping */
David Sedlák6881b512019-08-13 12:52:00 +02002182 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002183 grp->nodetype = LYS_GROUPING;
2184 grp->parent = gr_meta->parent;
2185
2186 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002187 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, LY_STMT_GROUPING));
David Sedláke3ce9ef2019-07-23 16:34:30 +02002188
2189 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002190 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002191 LY_STMT_ACTION, &grp->actions, 0,
2192 LY_STMT_ANYDATA, &grp->data, 0,
2193 LY_STMT_ANYXML, &grp->data, 0,
2194 LY_STMT_CHOICE, &grp->data, 0,
2195 LY_STMT_CONTAINER, &grp->data, 0,
2196 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2197 LY_STMT_GROUPING, &grp->groupings, 0,
2198 LY_STMT_LEAF, &grp->data, 0,
2199 LY_STMT_LEAF_LIST, &grp->data, 0,
2200 LY_STMT_LIST, &grp->data, 0,
2201 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2202 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2203 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2204 LY_STMT_TYPEDEF, &grp->typedefs, 0,
2205 LY_STMT_USES, &grp->data, 0,
2206 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002207 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002208 ret = yin_parse_content(ctx, subelems, 16, data, LY_STMT_GROUPING, NULL, &grp->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002209 subelems_deallocator(16, subelems);
2210 LY_CHECK_RET(ret);
2211
David Sedláke3ce9ef2019-07-23 16:34:30 +02002212 /* finalize parent pointers to the reallocated items */
2213 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2214
2215 return LY_SUCCESS;
2216}
2217
2218/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002219 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002220 *
2221 * @param[in,out] ctx YIN parser context for logging and to store current state.
2222 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2223 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002224 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002225 *
2226 * @return LY_ERR values.
2227 */
2228static LY_ERR
2229yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2230 struct tree_node_meta *node_meta)
2231{
David Sedlákf111bcb2019-07-23 17:15:51 +02002232 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002233 LY_ERR ret = LY_SUCCESS;
2234 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002235
2236 /* create new container */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02002237 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002238 cont->nodetype = LYS_CONTAINER;
2239 cont->parent = node_meta->parent;
2240
David Sedlákf111bcb2019-07-23 17:15:51 +02002241 /* parse aegument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002242 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, LY_STMT_CONTAINER));
David Sedlákf111bcb2019-07-23 17:15:51 +02002243
2244 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002245 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002246 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2247 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2248 LY_STMT_ANYXML, &cont->child, 0,
2249 LY_STMT_CHOICE, &cont->child, 0,
2250 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2251 LY_STMT_CONTAINER, &cont->child, 0,
2252 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2253 LY_STMT_GROUPING, &cont->groupings, 0,
2254 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2255 LY_STMT_LEAF, &cont->child, 0,
2256 LY_STMT_LEAF_LIST, &cont->child, 0,
2257 LY_STMT_LIST, &cont->child, 0,
2258 LY_STMT_MUST, &cont->musts, 0,
2259 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2260 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2261 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2262 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2263 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2264 LY_STMT_USES, &cont->child, 0,
2265 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2266 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002267 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002268 ret = yin_parse_content(ctx, subelems, 21, data, LY_STMT_CONTAINER, NULL, &cont->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002269 subelems_deallocator(21, subelems);
2270 LY_CHECK_RET(ret);
2271
David Sedlákf111bcb2019-07-23 17:15:51 +02002272 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2273
2274 return LY_SUCCESS;
2275}
2276
2277/**
David Sedlák5379d392019-07-24 10:42:03 +02002278 * @brief Parse case element.
2279 *
2280 * @param[in,out] ctx YIN parser context for logging and to store current state.
2281 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2282 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002283 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002284 *
2285 * @return LY_ERR values.
2286 */
2287static LY_ERR
2288yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2289 struct tree_node_meta *node_meta)
2290{
David Sedlák5379d392019-07-24 10:42:03 +02002291 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002292 LY_ERR ret = LY_SUCCESS;
2293 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002294
2295 /* create new case */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02002296 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002297 cas->nodetype = LYS_CASE;
2298 cas->parent = node_meta->parent;
2299
David Sedlák5379d392019-07-24 10:42:03 +02002300 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002301 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, LY_STMT_CASE));
David Sedlák5379d392019-07-24 10:42:03 +02002302
2303 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002304 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002305 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2306 LY_STMT_ANYXML, &cas->child, 0,
2307 LY_STMT_CHOICE, &cas->child, 0,
2308 LY_STMT_CONTAINER, &cas->child, 0,
2309 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2310 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2311 LY_STMT_LEAF, &cas->child, 0,
2312 LY_STMT_LEAF_LIST, &cas->child, 0,
2313 LY_STMT_LIST, &cas->child, 0,
2314 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2315 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2316 LY_STMT_USES, &cas->child, 0,
2317 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2318 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002319 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002320 ret = yin_parse_content(ctx, subelems, 14, data, LY_STMT_CASE, NULL, &cas->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002321 subelems_deallocator(14, subelems);
2322
2323 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002324}
2325
2326/**
David Sedlák05404f62019-07-24 14:11:53 +02002327 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002328 *
2329 * @param[in,out] ctx YIN parser context for logging and to store current state.
2330 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2331 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002332 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002333 *
2334 * @return LY_ERR values.
2335 */
2336LY_ERR
2337yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2338 struct tree_node_meta *node_meta)
2339{
David Sedlák81497a32019-08-13 16:56:26 +02002340 LY_ERR ret = LY_SUCCESS;
2341 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002342 struct lysp_node_choice *choice;
2343
2344 /* create new choice */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02002345 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002346
David Sedlákb7abcfa2019-07-24 12:33:35 +02002347 choice->nodetype = LYS_CHOICE;
2348 choice->parent = node_meta->parent;
2349
David Sedlákb7abcfa2019-07-24 12:33:35 +02002350 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002351 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, LY_STMT_CHOICE));
David Sedlákb7abcfa2019-07-24 12:33:35 +02002352
2353 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002354 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002355 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2356 LY_STMT_ANYXML, &choice->child, 0,
2357 LY_STMT_CASE, &choice->child, 0,
2358 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2359 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2360 LY_STMT_CONTAINER, &choice->child, 0,
2361 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2362 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2363 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2364 LY_STMT_LEAF, &choice->child, 0,
2365 LY_STMT_LEAF_LIST, &choice->child, 0,
2366 LY_STMT_LIST, &choice->child, 0,
2367 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2368 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2369 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2370 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2371 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002372 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002373 ret = yin_parse_content(ctx, subelems, 17, data, LY_STMT_CHOICE, NULL, &choice->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002374 subelems_deallocator(17, subelems);
2375 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002376}
2377
2378/**
David Sedlák05404f62019-07-24 14:11:53 +02002379 * @brief Parse input or output element.
2380 *
2381 * @param[in,out] ctx YIN parser context for logging and to store current state.
2382 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2383 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002384 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002385 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2386 *
2387 * @return LY_ERR values.
2388 */
2389static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02002390yin_parse_inout(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt inout_kw,
David Sedlák05404f62019-07-24 14:11:53 +02002391 struct inout_meta *inout_meta)
2392{
David Sedlák81497a32019-08-13 16:56:26 +02002393 LY_ERR ret = LY_SUCCESS;
2394 struct yin_subelement *subelems = NULL;
2395
David Sedlák05404f62019-07-24 14:11:53 +02002396 /* initiate structure */
Radek Krejcid6b76452019-09-03 17:03:03 +02002397 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002398 inout_meta->inout_p->parent = inout_meta->parent;
2399
2400 /* check attributes */
2401 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
2402
2403 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002404 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002405 LY_STMT_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2406 LY_STMT_ANYXML, &inout_meta->inout_p->data, 0,
2407 LY_STMT_CHOICE, &inout_meta->inout_p->data, 0,
2408 LY_STMT_CONTAINER, &inout_meta->inout_p->data, 0,
2409 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2410 LY_STMT_LEAF, &inout_meta->inout_p->data, 0,
2411 LY_STMT_LEAF_LIST, &inout_meta->inout_p->data, 0,
2412 LY_STMT_LIST, &inout_meta->inout_p->data, 0,
2413 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2414 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2415 LY_STMT_USES, &inout_meta->inout_p->data, 0,
2416 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002417 ));
2418 ret = yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts);
2419 subelems_deallocator(12, subelems);
2420 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002421
Michal Vaskob83af8a2020-01-06 09:49:22 +01002422 if (!inout_meta->inout_p->data) {
2423 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2424 return LY_EVALID;
2425 }
2426
David Sedlák05404f62019-07-24 14:11:53 +02002427 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002428 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 +02002429
2430 return LY_SUCCESS;
2431}
2432
David Sedlák992fb7c2019-07-24 16:51:01 +02002433/**
2434 * @brief Parse action element.
2435 *
2436 * @param[in,out] ctx YIN parser context for logging and to store current state.
2437 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2438 * @param[in,out] data Data to read from, always moved to currently handled character.
2439 * @param[in] act_meta Meta information about parent node and actions to add to.
2440 *
2441 * @return LY_ERR values.
2442 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002443static LY_ERR
2444yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002445 struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002446{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002447 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002448 LY_ERR ret = LY_SUCCESS;
2449 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002450
2451 /* create new action */
David Sedlák6881b512019-08-13 12:52:00 +02002452 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *acts, act, LY_EMEM);
David Sedlák85d0eca2019-07-24 15:15:21 +02002453 act->nodetype = LYS_ACTION;
2454 act->parent = act_meta->parent;
2455
2456 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002457 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, LY_STMT_ACTION));
David Sedlák85d0eca2019-07-24 15:15:21 +02002458
2459 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002460 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002461 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2462 LY_STMT_GROUPING, &act->groupings, 0,
2463 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2464 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2465 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2466 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2467 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2468 LY_STMT_TYPEDEF, &act->typedefs, 0,
2469 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002470 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002471 ret = (yin_parse_content(ctx, subelems, 9, data, LY_STMT_ACTION, NULL, &act->exts));
David Sedlák81497a32019-08-13 16:56:26 +02002472 subelems_deallocator(9, subelems);
2473 LY_CHECK_RET(ret);
2474
David Sedlák85d0eca2019-07-24 15:15:21 +02002475 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2476
2477 return LY_SUCCESS;
2478}
2479
David Sedlák05404f62019-07-24 14:11:53 +02002480/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002481 * @brief Parse augment element.
2482 *
2483 * @param[in,out] ctx YIN parser context for logging and to store current state.
2484 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2485 * @param[in,out] data Data to read from, always moved to currently handled character.
2486 * @param[in] aug_meta Meta information about parent node and augments to add to.
2487 *
2488 * @return LY_ERR values.
2489 */
2490static LY_ERR
2491yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002492 struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002493{
2494 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002495 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002496 LY_ERR ret = LY_SUCCESS;
2497 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002498
2499 /* create new augment */
David Sedlák6881b512019-08-13 12:52:00 +02002500 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002501 aug->nodetype = LYS_AUGMENT;
2502 aug->parent = aug_meta->parent;
2503
2504 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002505 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
David Sedlák992fb7c2019-07-24 16:51:01 +02002506 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2507
2508 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002509 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002510 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2511 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2512 LY_STMT_ANYXML, &aug->child, 0,
2513 LY_STMT_CASE, &aug->child, 0,
2514 LY_STMT_CHOICE, &aug->child, 0,
2515 LY_STMT_CONTAINER, &aug->child, 0,
2516 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2517 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
2518 LY_STMT_LEAF, &aug->child, 0,
2519 LY_STMT_LEAF_LIST, &aug->child, 0,
2520 LY_STMT_LIST, &aug->child, 0,
2521 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2522 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2523 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2524 LY_STMT_USES, &aug->child, 0,
2525 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2526 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002527 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002528 ret = yin_parse_content(ctx, subelems, 17, data, LY_STMT_AUGMENT, NULL, &aug->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002529 subelems_deallocator(17, subelems);
2530 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002531
2532 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2533
2534 return LY_SUCCESS;
2535}
2536
David Sedlák8b754462019-07-25 16:22:13 +02002537/**
2538 * @brief Parse deviate element.
2539 *
2540 * @param[in,out] ctx YIN parser context for logging and to store current state.
2541 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2542 * @param[in,out] data Data to read from, always moved to currently handled character.
2543 * @param[in] deviates Deviates to add to.
2544 *
2545 * @return LY_ERR values.
2546 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002547static LY_ERR
2548yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2549 struct lysp_deviate **deviates)
2550{
2551 LY_ERR ret = LY_SUCCESS;
2552 uint8_t dev_mod;
2553 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002554 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002555 struct lysp_deviate_add *d_add = NULL;
2556 struct lysp_deviate_rpl *d_rpl = NULL;
2557 struct lysp_deviate_del *d_del = NULL;
2558
2559 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002560 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_DEVIATE));
David Sedlák4ffcec82019-07-25 15:10:21 +02002561
2562 if (strcmp(temp_val, "not-supported") == 0) {
2563 dev_mod = LYS_DEV_NOT_SUPPORTED;
2564 } else if (strcmp(temp_val, "add") == 0) {
2565 dev_mod = LYS_DEV_ADD;
2566 } else if (strcmp(temp_val, "replace") == 0) {
2567 dev_mod = LYS_DEV_REPLACE;
2568 } else if (strcmp(temp_val, "delete") == 0) {
2569 dev_mod = LYS_DEV_DELETE;
2570 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002571 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
2572 "not-supported", "add", "replace", "delete");
David Sedlák4ffcec82019-07-25 15:10:21 +02002573 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2574 return LY_EVALID;
2575 }
2576 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2577
2578 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2579 d = calloc(1, sizeof *d);
2580 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2581 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002582 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák4ffcec82019-07-25 15:10:21 +02002583 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002584 ret = yin_parse_content(ctx, subelems, 1, data, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002585
2586 } else if (dev_mod == LYS_DEV_ADD) {
2587 d_add = calloc(1, sizeof *d_add);
2588 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2589 d = (struct lysp_deviate *)d_add;
2590 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2591 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2592 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002593 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2594 {LY_STMT_DEFAULT, &d_add->dflts, 0},
2595 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2596 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2597 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2598 {LY_STMT_MUST, &d_add->musts, 0},
2599 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2600 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2601 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002602 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002603 ret = yin_parse_content(ctx, subelems, 9, data, LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002604
2605 } else if (dev_mod == LYS_DEV_REPLACE) {
2606 d_rpl = calloc(1, sizeof *d_rpl);
2607 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2608 d = (struct lysp_deviate *)d_rpl;
2609 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2610 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2611 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002612 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2613 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2614 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2615 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2616 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2617 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2618 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2619 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002620 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002621 ret = yin_parse_content(ctx, subelems, 8, data, LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002622
2623 } else {
2624 d_del = calloc(1, sizeof *d_del);
2625 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2626 d = (struct lysp_deviate *)d_del;
2627 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002628 {LY_STMT_DEFAULT, &d_del->dflts, 0},
2629 {LY_STMT_MUST, &d_del->musts, 0},
2630 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2631 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2632 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002633 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002634 ret = yin_parse_content(ctx, subelems, 5, data, LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002635 }
2636 LY_CHECK_GOTO(ret, cleanup);
2637
2638 d->mod = dev_mod;
2639 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002640 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002641
2642 return ret;
2643
2644cleanup:
2645 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002646 return ret;
2647}
2648
David Sedlák992fb7c2019-07-24 16:51:01 +02002649/**
David Sedlák8b754462019-07-25 16:22:13 +02002650 * @brief Parse deviation element.
2651 *
2652 * @param[in,out] ctx YIN parser context for logging and to store current state.
2653 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2654 * @param[in,out] data Data to read from, always moved to currently handled character.
2655 * @param[in] deviations Deviations to add to.
2656 *
2657 * @return LY_ERR values.
2658 */
2659static LY_ERR
2660yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2661 struct lysp_deviation **deviations)
2662{
2663 struct lysp_deviation *dev;
2664
2665 /* create new deviation */
2666 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2667
2668 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002669 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
David Sedlák8b754462019-07-25 16:22:13 +02002670 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2671 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002672 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2673 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2674 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2675 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8b754462019-07-25 16:22:13 +02002676 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002677 return yin_parse_content(ctx, subelems, 4, data, LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002678}
2679
2680/**
David Sedlákb4e44562019-07-04 15:42:12 +02002681 * @brief Map keyword type to substatement info.
2682 *
2683 * @param[in] kw Keyword type.
2684 *
2685 * @return correct LYEXT_SUBSTMT information.
2686 */
2687static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002688kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002689{
2690 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002691 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002692 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002693 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002694 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002695 case LY_STMT_BELONGS_TO:
David Sedlákb4e44562019-07-04 15:42:12 +02002696 return LYEXT_SUBSTMT_BELONGSTO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002697 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002698 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002699 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002700 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002701 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002702 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002703 case LY_STMT_ERROR_APP_TAG:
David Sedlákb4e44562019-07-04 15:42:12 +02002704 return LYEXT_SUBSTMT_ERRTAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002705 case LY_STMT_ERROR_MESSAGE:
David Sedlákb4e44562019-07-04 15:42:12 +02002706 return LYEXT_SUBSTMT_ERRMSG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002707 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002708 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002709 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002710 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002711 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002712 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002713 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002714 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002715 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002716 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002717 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002718 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002719 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002720 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002721 case LY_STMT_REVISION_DATE:
David Sedlákb4e44562019-07-04 15:42:12 +02002722 return LYEXT_SUBSTMT_REVISIONDATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002723 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002724 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002725 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002726 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002727 case LY_STMT_YANG_VERSION:
David Sedlákb4e44562019-07-04 15:42:12 +02002728 return LYEXT_SUBSTMT_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002729 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002730 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002731 case LY_STMT_REQUIRE_INSTANCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002732 return LYEXT_SUBSTMT_REQINSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002733 case LY_STMT_YIN_ELEMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002734 return LYEXT_SUBSTMT_YINELEM;
Radek Krejcid6b76452019-09-03 17:03:03 +02002735 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002736 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002737 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002738 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002739 case LY_STMT_ORDERED_BY:
David Sedlákb4e44562019-07-04 15:42:12 +02002740 return LYEXT_SUBSTMT_ORDEREDBY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002741 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002742 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002743 case LY_STMT_FRACTION_DIGITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002744 return LYEXT_SUBSTMT_FRACDIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002745 case LY_STMT_MAX_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002746 return LYEXT_SUBSTMT_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002747 case LY_STMT_MIN_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002748 return LYEXT_SUBSTMT_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02002749 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002750 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002751 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002752 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002753 case LY_STMT_IF_FEATURE:
David Sedlákb4e44562019-07-04 15:42:12 +02002754 return LYEXT_SUBSTMT_IFFEATURE;
2755 default:
2756 return LYEXT_SUBSTMT_SELF;
2757 }
2758}
2759
David Sedlákc5b20842019-08-13 10:18:31 +02002760/**
2761 * @brief map keyword to keyword-group.
2762 *
2763 * @param[in] ctx YIN parser context used for logging.
2764 * @param[in] kw Keyword that is child of module or submodule.
2765 * @param[out] group Group of keyword.
2766 *
2767 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2768 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002769static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02002770kw2kw_group(struct yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002771{
2772 switch (kw) {
2773 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02002774 case LY_STMT_NONE:
2775 case LY_STMT_NAMESPACE:
2776 case LY_STMT_PREFIX:
2777 case LY_STMT_BELONGS_TO:
2778 case LY_STMT_YANG_VERSION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002779 *group = Y_MOD_MODULE_HEADER;
2780 break;
2781 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02002782 case LY_STMT_INCLUDE:
2783 case LY_STMT_IMPORT:
David Sedláke6cd89e2019-08-07 12:46:02 +02002784 *group = Y_MOD_LINKAGE;
2785 break;
2786 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02002787 case LY_STMT_ORGANIZATION:
2788 case LY_STMT_CONTACT:
2789 case LY_STMT_DESCRIPTION:
2790 case LY_STMT_REFERENCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002791 *group = Y_MOD_META;
2792 break;
2793 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02002794 case LY_STMT_REVISION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002795 *group = Y_MOD_REVISION;
2796 break;
2797 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02002798 case LY_STMT_ANYDATA:
2799 case LY_STMT_ANYXML:
2800 case LY_STMT_AUGMENT:
2801 case LY_STMT_CHOICE:
2802 case LY_STMT_CONTAINER:
2803 case LY_STMT_DEVIATION:
2804 case LY_STMT_EXTENSION:
2805 case LY_STMT_FEATURE:
2806 case LY_STMT_GROUPING:
2807 case LY_STMT_IDENTITY:
2808 case LY_STMT_LEAF:
2809 case LY_STMT_LEAF_LIST:
2810 case LY_STMT_LIST:
2811 case LY_STMT_NOTIFICATION:
2812 case LY_STMT_RPC:
2813 case LY_STMT_TYPEDEF:
2814 case LY_STMT_USES:
2815 case LY_STMT_EXTENSION_INSTANCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002816 *group = Y_MOD_BODY;
2817 break;
2818 default:
2819 LOGINT(ctx->xml_ctx.ctx);
2820 return LY_EINT;
2821 }
2822
2823 return LY_SUCCESS;
2824}
2825
David Sedlákc5b20842019-08-13 10:18:31 +02002826/**
2827 * @brief Check if relative order of two keywords is valid.
2828 *
2829 * @param[in] ctx YIN parser context used for logging.
2830 * @param[in] kw Current keyword.
2831 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002832 * @param[in] parrent Identification of parrent element, can be se to to LY_STMT_MODULE of LY_STMT_SUBMODULE,
David Sedlákc5b20842019-08-13 10:18:31 +02002833 * because relative order is required only in module and submodule sub-elements, used for logging.
2834 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002835 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002836 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002837static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02002838yin_check_relative_order(struct yin_parser_ctx *ctx, enum ly_stmt kw, enum ly_stmt next_kw, enum ly_stmt parrent)
David Sedláke6cd89e2019-08-07 12:46:02 +02002839{
Radek Krejcid6b76452019-09-03 17:03:03 +02002840 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002841 enum yang_module_stmt gr, next_gr;
2842
2843 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2844 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2845
2846 if (gr > next_gr) {
2847 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2848 return LY_EVALID;
2849 }
2850
2851 return LY_SUCCESS;
2852}
2853
David Sedlákc5dd0942019-09-13 10:23:59 +02002854/**
2855 * @brief Get element name prefixed by full URI of xml namespace.
2856 *
2857 * @param[in] ctx YIN parser context used for logging and to get inormation about xml namespaces.
2858 * @param[in] name Name of element.
2859 * @param[in] name_len Length of element name.
2860 * @param[in] prefix Prefix of element.
2861 * @param[in] prefix_len Length of element prefix.
2862 *
2863 * @return Element name prefixed by URI on success, NULL on failure.
2864 */
2865static const char *
David Sedlák068dd352019-09-13 09:08:22 +02002866name2nsname(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len)
2867{
2868 const struct lyxml_ns *ns = lyxml_ns_get(&ctx->xml_ctx, prefix, prefix_len);
David Sedláke0ef1c62019-09-13 10:05:55 +02002869 LY_CHECK_ERR_RET(!ns, LOGINT(ctx->xml_ctx.ctx), NULL);
David Sedlák068dd352019-09-13 09:08:22 +02002870
Radek Krejci02728562019-09-18 14:13:05 +02002871 if (!strcmp(ns->uri, YIN_NS_URI)) {
2872 /* standard YANG statement in YIN namespace - keep it unprefixed as in case of YANG */
2873 return lydict_insert(ctx->xml_ctx.ctx, name, name_len);
2874 }
2875 /* some statement in special namespace (extension instance) */
David Sedláke0ef1c62019-09-13 10:05:55 +02002876 size_t ns_len = strlen(ns->uri);
2877 size_t len = ns_len + name_len + 1; /* +1 because of ':' delimiter between ns and actual name */
2878
2879 char *result;
2880 char *temp;
2881 temp = result = malloc(sizeof(*temp) * (len + 1)); /* +1 for '\0' terminator */
2882 LY_CHECK_ERR_RET(!temp, LOGMEM(ctx->xml_ctx.ctx), NULL);
2883
2884 strcpy(result, ns->uri);
2885 result[ns_len] = ':';
2886 temp = &result[ns_len + 1];
2887 strncpy(temp, name, name_len);
2888 result[len] = '\0';
2889
2890 return lydict_insert_zc(ctx->xml_ctx.ctx, result);
David Sedlák068dd352019-09-13 09:08:22 +02002891}
2892
David Sedlákd6e56892019-07-01 15:40:24 +02002893LY_ERR
Radek Krejci12b1c152019-09-05 16:20:48 +02002894yin_parse_content(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
Radek Krejcid6b76452019-09-03 17:03:03 +02002895 const char **data, enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02002896{
2897 LY_ERR ret = LY_SUCCESS;
David Sedlák8e7bda82019-07-16 17:57:50 +02002898 char *out = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +02002899 const char *prefix, *name;
2900 size_t out_len = 0, prefix_len, name_len;
David Sedlák8e7bda82019-07-16 17:57:50 +02002901 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002902 struct yin_arg_record *attrs = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +02002903 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002904 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002905
David Sedlákda8ffa32019-07-08 14:17:10 +02002906 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2907 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002908 /* current element has subelements as content */
2909 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002910 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákc5b20842019-08-13 10:18:31 +02002911 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákd6e56892019-07-01 15:40:24 +02002912 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +02002913 if (!name) {
David Sedlákd6e56892019-07-01 15:40:24 +02002914 /* end of current element reached */
2915 break;
2916 }
David Sedlák1af868e2019-07-17 17:03:14 +02002917 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002918 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6cd89e2019-08-07 12:46:02 +02002919 last_kw = kw;
David Sedlákc5b20842019-08-13 10:18:31 +02002920 kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002921
2922 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002923 subelem = get_record(kw, subelem_info_size, subelem_info);
2924 if (!subelem) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002925 if (current_element == LY_STMT_DEVIATE && isdevsub(kw)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002926 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2927 } else {
David Sedlákc5b20842019-08-13 10:18:31 +02002928 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 +02002929 }
David Sedlákd6e56892019-07-01 15:40:24 +02002930 ret = LY_EVALID;
2931 goto cleanup;
2932 }
2933
David Sedlák6542aed2019-08-14 10:47:43 +02002934 /* relative order is required only in module and submodule sub-elements */
Radek Krejcid6b76452019-09-03 17:03:03 +02002935 if (current_element == LY_STMT_MODULE || current_element == LY_STMT_SUBMODULE) {
David Sedláke6cd89e2019-08-07 12:46:02 +02002936 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2937 LY_CHECK_GOTO(ret, cleanup);
2938 }
David Sedlák5f8191e2019-07-08 16:35:52 +02002939
David Sedlák4ffcec82019-07-25 15:10:21 +02002940 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002941 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002942 /* subelement uniquenes */
David Sedlák1538a842019-08-08 15:38:51 +02002943 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 +02002944 return LY_EVALID;
2945 }
David Sedlák1af868e2019-07-17 17:03:14 +02002946 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002947 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002948 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002949 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002950 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002951 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002952 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002953 if (ctx->mod_version < 2) {
David Sedlák1538a842019-08-08 15:38:51 +02002954 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 +02002955 ret = LY_EVALID;
2956 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002957 }
2958 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002959 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002960 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002961
David Sedlákd6e56892019-07-01 15:40:24 +02002962 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002963 /* call responsible function */
Radek Krejcid6b76452019-09-03 17:03:03 +02002964 case LY_STMT_EXTENSION_INSTANCE:
David Sedláke0ef1c62019-09-13 10:05:55 +02002965 ret = yin_parse_extension_instance(ctx, attrs, data, name, name_len, prefix, prefix_len,
David Sedlák1af868e2019-07-17 17:03:14 +02002966 kw2lyext_substmt(current_element),
2967 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002968 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002969 case LY_STMT_ACTION:
2970 case LY_STMT_RPC:
David Sedlák6881b512019-08-13 12:52:00 +02002971 ret = yin_parse_action(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002972 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002973 case LY_STMT_ANYDATA:
2974 case LY_STMT_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002975 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002976 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002977 case LY_STMT_ARGUMENT:
David Sedlákdf2691f2019-08-15 13:32:27 +02002978 ret = yin_parse_argument(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002979 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002980 case LY_STMT_AUGMENT:
David Sedlák6881b512019-08-13 12:52:00 +02002981 ret = yin_parse_augment(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002982 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002983 case LY_STMT_BASE:
David Sedlák6542aed2019-08-14 10:47:43 +02002984 ret = yin_parse_base(ctx, attrs, data, current_element, subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002985 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002986 case LY_STMT_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002987 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002988 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002989 case LY_STMT_BIT:
David Sedlák43801c92019-08-05 15:58:54 +02002990 ret = yin_parse_bit(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002991 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002992 case LY_STMT_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002993 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002994 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002995 case LY_STMT_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002996 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002997 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002998 case LY_STMT_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02002999 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003000 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003001 case LY_STMT_CONTACT:
3002 case LY_STMT_DESCRIPTION:
3003 case LY_STMT_ORGANIZATION:
3004 case LY_STMT_REFERENCE:
David Sedlákdf2691f2019-08-15 13:32:27 +02003005 ret = yin_parse_meta(ctx, attrs, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003006 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003007 case LY_STMT_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02003008 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003009 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003010 case LY_STMT_DEFAULT:
3011 case LY_STMT_ERROR_APP_TAG:
3012 case LY_STMT_KEY:
3013 case LY_STMT_PRESENCE:
David Sedlák6542aed2019-08-14 10:47:43 +02003014 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 +02003015 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003016 case LY_STMT_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02003017 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003018 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003019 case LY_STMT_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02003020 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003021 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003022 case LY_STMT_ENUM:
David Sedlák43801c92019-08-05 15:58:54 +02003023 ret = yin_parse_enum(ctx, attrs, data, (struct lysp_type *)subelem->dest);
3024 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003025 case LY_STMT_ERROR_MESSAGE:
David Sedlákdf2691f2019-08-15 13:32:27 +02003026 ret = yin_parse_err_msg(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003027 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003028 case LY_STMT_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003029 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003030 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003031 case LY_STMT_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02003032 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003033 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003034 case LY_STMT_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02003035 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003036 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003037 case LY_STMT_GROUPING:
David Sedlák6881b512019-08-13 12:52:00 +02003038 ret = yin_parse_grouping(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003039 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003040 case LY_STMT_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02003041 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003042 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003043 case LY_STMT_IF_FEATURE:
3044 case LY_STMT_UNITS:
David Sedlák6542aed2019-08-14 10:47:43 +02003045 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 +02003046 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003047 case LY_STMT_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02003048 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003049 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003050 case LY_STMT_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02003051 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003052 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003053 case LY_STMT_INPUT:
3054 case LY_STMT_OUTPUT:
David Sedlák05404f62019-07-24 14:11:53 +02003055 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003056 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003057 case LY_STMT_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02003058 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003059 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003060 case LY_STMT_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02003061 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003062 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003063 case LY_STMT_LENGTH:
David Sedlák6542aed2019-08-14 10:47:43 +02003064 ret = yin_parse_length(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003065 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003066 case LY_STMT_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02003067 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003068 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003069 case LY_STMT_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02003070 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003071 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003072 case LY_STMT_MAX_ELEMENTS:
3073 case LY_STMT_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02003074 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003075 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003076 case LY_STMT_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02003077 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003078 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003079 case LY_STMT_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02003080 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003081 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003082 case LY_STMT_NAMESPACE:
David Sedlák6542aed2019-08-14 10:47:43 +02003083 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 +02003084 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003085 case LY_STMT_NOTIFICATION:
David Sedlák6881b512019-08-13 12:52:00 +02003086 ret = yin_parse_notification(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003087 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003088 case LY_STMT_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02003089 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003090 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003091 case LY_STMT_PATH:
David Sedlák6542aed2019-08-14 10:47:43 +02003092 ret = yin_parse_path(ctx, attrs, data, kw, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003093 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003094 case LY_STMT_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02003095 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003096 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003097 case LY_STMT_VALUE:
3098 case LY_STMT_POSITION:
David Sedlákdf2691f2019-08-15 13:32:27 +02003099 ret = yin_parse_value_pos(ctx, attrs, data, kw, (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003100 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003101 case LY_STMT_PREFIX:
David Sedlák6542aed2019-08-14 10:47:43 +02003102 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 +02003103 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003104 case LY_STMT_RANGE:
David Sedlák6542aed2019-08-14 10:47:43 +02003105 ret = yin_parse_range(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003106 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003107 case LY_STMT_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02003108 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003109 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003110 case LY_STMT_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02003111 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003112 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003113 case LY_STMT_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02003114 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003115 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003116 case LY_STMT_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02003117 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003118 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003119 case LY_STMT_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02003120 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003121 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003122 case LY_STMT_TYPE:
David Sedlák6542aed2019-08-14 10:47:43 +02003123 ret = yin_parse_type(ctx, attrs, data, current_element, subelem);
David Sedlákd6e56892019-07-01 15:40:24 +02003124 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003125 case LY_STMT_TYPEDEF:
David Sedlák6881b512019-08-13 12:52:00 +02003126 ret = yin_parse_typedef(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003127 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003128 case LY_STMT_UNIQUE:
David Sedlák6542aed2019-08-14 10:47:43 +02003129 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 +02003130 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003131 case LY_STMT_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02003132 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003133 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003134 case LY_STMT_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02003135 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003136 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003137 case LY_STMT_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003138 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003139 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003140 case LY_STMT_YIN_ELEMENT:
David Sedlákdf2691f2019-08-15 13:32:27 +02003141 ret = yin_parse_yin_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02003142 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003143 case LY_STMT_ARG_TEXT:
3144 case LY_STMT_ARG_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02003145 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02003146 break;
3147 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02003148 LOGINT(ctx->xml_ctx.ctx);
David Sedlákbf8a2b72019-08-14 16:48:10 +02003149 ret = LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02003150 }
David Sedlák3ffbc522019-07-02 17:49:28 +02003151 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02003152 FREE_ARRAY(ctx, attrs, free_arg_rec);
3153 attrs = NULL;
3154 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02003155 }
3156 } else {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003157 LY_CHECK_RET(ret);
David Sedlákd6e56892019-07-01 15:40:24 +02003158 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02003159 /* save text content, if text_content isn't set, it's just ignored */
David Sedlákc5b20842019-08-13 10:18:31 +02003160 /* no resources are allocated in this branch, no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02003161 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02003162 if (text_content) {
David Sedlák169cc522019-08-15 13:23:45 +02003163 INSERT_STRING(ctx->xml_ctx.ctx, *text_content, dynamic, out, out_len);
3164 LY_CHECK_RET(!*text_content, LY_EMEM);
David Sedlák3ffbc522019-07-02 17:49:28 +02003165 }
David Sedlákd6e56892019-07-01 15:40:24 +02003166 /* load closing element */
David Sedlákc5b20842019-08-13 10:18:31 +02003167 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákd6e56892019-07-01 15:40:24 +02003168 }
3169 }
David Sedlák8b754462019-07-25 16:22:13 +02003170 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3171 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003172
3173cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02003174 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02003175 return ret;
3176}
3177
David Sedlák619db942019-07-03 14:47:30 +02003178LY_ERR
David Sedláke0ef1c62019-09-13 10:05:55 +02003179yin_parse_extension_instance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
3180 const char *ext_name, size_t ext_name_len, const char *ext_prefix, size_t ext_prefix_len,
3181 LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003182{
3183 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003184 char *out;
3185 const char *name, *prefix;
3186 size_t out_len, prefix_len, name_len;
3187 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003188 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003189 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
3190 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003191
David Sedlákda8ffa32019-07-08 14:17:10 +02003192 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003193
3194 e->yin = 0;
3195 /* store name and insubstmt info */
David Sedláke0ef1c62019-09-13 10:05:55 +02003196 e->name = name2nsname(ctx, ext_name, ext_name_len, ext_prefix, ext_prefix_len);
3197 LY_CHECK_RET(!e->name, LY_EMEM);
David Sedlák619db942019-07-03 14:47:30 +02003198 e->insubstmt = subelem;
3199 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003200 e->yin |= LYS_YIN;
3201
David Sedlákb1a78352019-06-28 16:16:29 +02003202 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02003203 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02003204 if (!iter->prefix) {
3205 new_subelem = calloc(1, sizeof(*new_subelem));
3206 if (!e->child) {
3207 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003208 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003209 last_subelem->next = new_subelem;
3210 }
3211 last_subelem = new_subelem;
3212
3213 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003214 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
David Sedlák169cc522019-08-15 13:23:45 +02003215 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3216
3217 INSERT_STRING(ctx->xml_ctx.ctx, last_subelem->arg, iter->dynamic_content, iter->content, iter->content_len);
3218 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003219 }
3220 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003221
David Sedlákf250ecf2019-07-01 11:02:05 +02003222 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003223 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3224 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003225 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003226 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3227 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02003228 if (!name) {
3229 /* end of extension instance reached */
3230 break;
3231 }
David Sedlák071f7662019-09-12 02:02:51 +02003232 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, prefix, prefix_len, LY_STMT_EXTENSION_INSTANCE, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02003233 if (!e->child) {
3234 e->child = new_subelem;
3235 } else {
3236 last_subelem->next = new_subelem;
3237 }
3238 last_subelem = new_subelem;
3239 }
David Sedlák555c7202019-07-04 12:14:12 +02003240 } else {
David Sedlák169cc522019-08-15 13:23:45 +02003241 if (out_len != 0) {
3242 /* save text content */
3243 LY_CHECK_RET(ret);
3244
3245 INSERT_STRING(ctx->xml_ctx.ctx, e->argument, dynamic, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02003246 LY_CHECK_RET(!e->argument, LY_EMEM);
David Sedlák169cc522019-08-15 13:23:45 +02003247
3248 /* load closing element */
3249 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
3250 LY_CHECK_RET(name, LY_EINT);
David Sedlák555c7202019-07-04 12:14:12 +02003251 }
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
David Sedlákaa98bba2019-09-12 11:52:14 +02003258/**
3259 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
3260 *
3261 * @param[in,out] ctx Yin parser context for logging and to store current state.
3262 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension instance.
3263 * @param[in,out] data Data to read from, always moved to currently handled character.
3264 * @param[in] elem_type Type of element that is currently being parsed.
3265 * @param[out] arg Value to write to.
3266 *
3267 * @return LY_ERR values.
3268 */
3269static LY_ERR
David Sedlákd2844882019-09-13 16:01:22 +02003270yin_parse_extension_instance_arg(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt elem_type,
David Sedlákd6502182019-09-13 11:11:28 +02003271 const char **arg)
David Sedláke6284fc2019-09-10 11:57:02 +02003272{
David Sedláke6284fc2019-09-10 11:57:02 +02003273 LY_ERR ret = LY_SUCCESS;
David Sedlák071f7662019-09-12 02:02:51 +02003274 char *out = NULL;
3275 const char *name, *prefix;
3276 size_t out_len, name_len, prefix_len;
3277 int dynamic;
3278 enum ly_stmt child;
David Sedláke6284fc2019-09-10 11:57:02 +02003279
David Sedláke6284fc2019-09-10 11:57:02 +02003280 switch (elem_type) {
3281 case LY_STMT_ACTION:
3282 case LY_STMT_ANYDATA:
3283 case LY_STMT_ANYXML:
3284 case LY_STMT_ARGUMENT:
3285 case LY_STMT_BASE:
3286 case LY_STMT_BIT:
3287 case LY_STMT_CASE:
3288 case LY_STMT_CHOICE:
3289 case LY_STMT_CONTAINER:
3290 case LY_STMT_ENUM:
3291 case LY_STMT_EXTENSION:
3292 case LY_STMT_FEATURE:
3293 case LY_STMT_GROUPING:
3294 case LY_STMT_IDENTITY:
3295 case LY_STMT_IF_FEATURE:
3296 case LY_STMT_LEAF:
3297 case LY_STMT_LEAF_LIST:
3298 case LY_STMT_LIST:
3299 case LY_STMT_MODULE:
3300 case LY_STMT_NOTIFICATION:
3301 case LY_STMT_RPC:
3302 case LY_STMT_SUBMODULE:
3303 case LY_STMT_TYPE:
3304 case LY_STMT_TYPEDEF:
3305 case LY_STMT_UNITS:
3306 case LY_STMT_USES:
David Sedlákaa98bba2019-09-12 11:52:14 +02003307 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003308 break;
3309 case LY_STMT_AUGMENT:
3310 case LY_STMT_DEVIATION:
3311 case LY_STMT_REFINE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003312 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003313 break;
3314 case LY_STMT_CONFIG:
3315 case LY_STMT_DEFAULT:
3316 case LY_STMT_DEVIATE:
3317 case LY_STMT_ERROR_APP_TAG:
David Sedláke6284fc2019-09-10 11:57:02 +02003318 case LY_STMT_FRACTION_DIGITS:
3319 case LY_STMT_KEY:
3320 case LY_STMT_LENGTH:
3321 case LY_STMT_MANDATORY:
3322 case LY_STMT_MAX_ELEMENTS:
3323 case LY_STMT_MIN_ELEMENTS:
3324 case LY_STMT_MODIFIER:
3325 case LY_STMT_ORDERED_BY:
3326 case LY_STMT_PATH:
3327 case LY_STMT_PATTERN:
3328 case LY_STMT_POSITION:
3329 case LY_STMT_PREFIX:
3330 case LY_STMT_PRESENCE:
3331 case LY_STMT_RANGE:
3332 case LY_STMT_REQUIRE_INSTANCE:
3333 case LY_STMT_STATUS:
3334 case LY_STMT_VALUE:
3335 case LY_STMT_YANG_VERSION:
3336 case LY_STMT_YIN_ELEMENT:
David Sedlákaa98bba2019-09-12 11:52:14 +02003337 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003338 break;
3339 case LY_STMT_IMPORT:
3340 case LY_STMT_INCLUDE:
3341 case LY_STMT_BELONGS_TO:
David Sedlákaa98bba2019-09-12 11:52:14 +02003342 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003343 break;
3344 case LY_STMT_INPUT:
3345 case LY_STMT_OUTPUT:
David Sedlákaa98bba2019-09-12 11:52:14 +02003346 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003347 break;
3348 case LY_STMT_MUST:
3349 case LY_STMT_WHEN:
David Sedlákaa98bba2019-09-12 11:52:14 +02003350 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003351 break;
3352 case LY_STMT_NAMESPACE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003353 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003354 break;
3355 case LY_STMT_REVISION:
3356 case LY_STMT_REVISION_DATE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003357 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003358 break;
3359 case LY_STMT_UNIQUE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003360 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003361 break;
David Sedlák071f7662019-09-12 02:02:51 +02003362 /* argument is mapped to yin element */
3363 case LY_STMT_CONTACT:
3364 case LY_STMT_DESCRIPTION:
3365 case LY_STMT_ORGANIZATION:
3366 case LY_STMT_REFERENCE:
3367 case LY_STMT_ERROR_MESSAGE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003368 /* there shouldn't be any attribute, argument is supposed to be first subelement */
3369 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedlák071f7662019-09-12 02:02:51 +02003370 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákaa98bba2019-09-12 11:52:14 +02003371 LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
3372 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type)),
3373 LY_EVALID);
David Sedlák071f7662019-09-12 02:02:51 +02003374 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
3375 child = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, elem_type);
David Sedlákd2844882019-09-13 16:01:22 +02003376 if ((elem_type == LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_VALUE) ||
3377 (elem_type != LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_TEXT)) {
David Sedlákaa98bba2019-09-12 11:52:14 +02003378 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(elem_type));
David Sedlák071f7662019-09-12 02:02:51 +02003379 return LY_EVALID;
3380 }
3381 /* load and save content */
3382 LY_CHECK_RET(lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic));
David Sedlákaa98bba2019-09-12 11:52:14 +02003383 INSERT_STRING(ctx->xml_ctx.ctx, *arg, dynamic, out, out_len);
3384 LY_CHECK_RET(!*arg, LY_EMEM);
3385 /* load closing tag of subelement */
David Sedlák071f7662019-09-12 02:02:51 +02003386 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákaa98bba2019-09-12 11:52:14 +02003387 /* if only subelement was parsed as argument, load also closing tag */
3388 if (ctx->xml_ctx.status == LYXML_ELEMENT) {
3389 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
3390 }
David Sedlákb0ca07d2019-09-11 11:54:05 +02003391 break;
David Sedláke6284fc2019-09-10 11:57:02 +02003392 default:
3393 LOGINT(ctx->xml_ctx.ctx);
David Sedlák071f7662019-09-12 02:02:51 +02003394 return LY_EINT;
David Sedláke6284fc2019-09-10 11:57:02 +02003395 }
3396
David Sedlák071f7662019-09-12 02:02:51 +02003397 return LY_SUCCESS;
David Sedláke6284fc2019-09-10 11:57:02 +02003398}
3399
3400LY_ERR
David Sedlákaa98bba2019-09-12 11:52:14 +02003401yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, enum ly_stmt parent,
David Sedlák071f7662019-09-12 02:02:51 +02003402 const char **data, struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02003403{
3404 LY_ERR ret = LY_SUCCESS;
3405 const char *temp_prefix, *temp_name;
3406 char *out = NULL;
Radek Krejci6df08da2019-09-09 14:07:21 +02003407 size_t out_len, temp_name_len, temp_prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02003408 int dynamic;
David Sedlákb1a78352019-06-28 16:16:29 +02003409 struct lysp_stmt *last = NULL, *new = NULL;
David Sedlákb0ca07d2019-09-11 11:54:05 +02003410 struct yin_arg_record *attrs = NULL;
3411 struct yin_arg_record *iter = NULL;
David Sedlákb1a78352019-06-28 16:16:29 +02003412
David Sedláke0ef1c62019-09-13 10:05:55 +02003413 /* load all attributes for correct namespace evaluation */
David Sedlákb0ca07d2019-09-11 11:54:05 +02003414 ret = yin_load_attributes(ctx, data, &attrs);
3415 LY_CHECK_GOTO(ret, cleanup);
David Sedláke0ef1c62019-09-13 10:05:55 +02003416
3417 /* allocate new structure for element */
3418 *element = calloc(1, sizeof(**element));
3419 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedláke0ef1c62019-09-13 10:05:55 +02003420 (*element)->stmt = name2nsname(ctx, name, name_len, prefix, prefix_len);
3421 LY_CHECK_ERR_GOTO(!(*element)->stmt, ret = LY_EMEM, cleanup);
David Sedláke0ef1c62019-09-13 10:05:55 +02003422
David Sedlákaa98bba2019-09-12 11:52:14 +02003423 (*element)->kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, parent);
David Sedlákb1a78352019-06-28 16:16:29 +02003424
3425 last = (*element)->child;
David Sedláke6284fc2019-09-10 11:57:02 +02003426 if ((*element)->kw == LY_STMT_NONE) {
3427 /* unrecognized element */
David Sedlákaa98bba2019-09-12 11:52:14 +02003428 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(parent));
3429 ret = LY_EVALID;
3430 goto cleanup;
David Sedláke6284fc2019-09-10 11:57:02 +02003431 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3432 /* element is known yang keyword, which means argument can be parsed correctly. */
David Sedlákd2844882019-09-13 16:01:22 +02003433 ret = yin_parse_extension_instance_arg(ctx, attrs, data, (*element)->kw, &(*element)->arg);
David Sedlákaa98bba2019-09-12 11:52:14 +02003434 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003435 } else {
David Sedlákaa98bba2019-09-12 11:52:14 +02003436 /* load attributes in generic way, save all attributes in linked list */
David Sedlákb0ca07d2019-09-11 11:54:05 +02003437 LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
David Sedláke6284fc2019-09-10 11:57:02 +02003438 new = calloc(1, sizeof(*last));
David Sedlákaa98bba2019-09-12 11:52:14 +02003439 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003440 if (!(*element)->child) {
3441 /* save first */
3442 (*element)->child = new;
3443 } else {
3444 last->next = new;
3445 }
3446 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003447
David Sedláke6284fc2019-09-10 11:57:02 +02003448 last->flags |= LYS_YIN_ATTR;
David Sedlákb0ca07d2019-09-11 11:54:05 +02003449 last->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
3450 last->kw = LY_STMT_NONE;
David Sedláke6284fc2019-09-10 11:57:02 +02003451 /* attributes with prefix are ignored */
David Sedlákb0ca07d2019-09-11 11:54:05 +02003452 if (!iter->prefix) {
3453 INSERT_STRING(ctx->xml_ctx.ctx, last->arg, iter->dynamic_content, iter->content, iter->content_len);
David Sedlákaa98bba2019-09-12 11:52:14 +02003454 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
David Sedlákb0ca07d2019-09-11 11:54:05 +02003455 /* string is no longer supposed to be freed when the array is freed */
3456 iter->dynamic_content = 0;
David Sedláka82ecff2019-08-16 10:51:48 +02003457 }
David Sedlákb1a78352019-06-28 16:16:29 +02003458 }
3459 }
3460
David Sedláka82ecff2019-08-16 10:51:48 +02003461 /* parse content of element if any */
3462 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3463 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
3464 if (ret == LY_EINVAL) {
3465 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3466 /* parse subelements */
David Sedlákaa98bba2019-09-12 11:52:14 +02003467 ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
3468 LY_CHECK_GOTO(ret , cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003469 if (!temp_name) {
3470 /* end of element reached */
3471 break;
3472 }
David Sedlákaa98bba2019-09-12 11:52:14 +02003473 ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, (*element)->kw, data, &new);
3474 LY_CHECK_GOTO(ret, cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003475 if (!(*element)->child) {
3476 /* save first */
3477 (*element)->child = new;
3478 } else {
3479 last->next = new;
3480 }
3481 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003482 }
David Sedlákb0ca07d2019-09-11 11:54:05 +02003483 ret = LY_SUCCESS;
David Sedláka82ecff2019-08-16 10:51:48 +02003484 } else {
David Sedlákaa98bba2019-09-12 11:52:14 +02003485 LY_CHECK_GOTO(ret, cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003486 /* save element content */
3487 if (out_len != 0) {
3488 INSERT_STRING(ctx->xml_ctx.ctx, (*element)->arg, dynamic, out, out_len);
David Sedlákaa98bba2019-09-12 11:52:14 +02003489 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003490 }
David Sedlák169cc522019-08-15 13:23:45 +02003491
David Sedláka82ecff2019-08-16 10:51:48 +02003492 /* read closing tag */
David Sedlákaa98bba2019-09-12 11:52:14 +02003493 ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
3494 LY_CHECK_GOTO(ret, cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003495 }
David Sedlákb1a78352019-06-28 16:16:29 +02003496 }
3497
David Sedlákb0ca07d2019-09-11 11:54:05 +02003498cleanup:
3499 FREE_ARRAY(ctx, attrs, free_arg_rec);
3500 return ret;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003501}
3502
3503LY_ERR
David Sedlák4f03b932019-07-26 13:01:47 +02003504yin_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 +02003505{
David Sedlák81497a32019-08-13 16:56:26 +02003506 LY_ERR ret = LY_SUCCESS;
3507 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003508 struct lysp_submodule *dup;
David Sedlák3b4db242018-10-19 16:11:01 +02003509
Radek Krejcid6b76452019-09-03 17:03:03 +02003510 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, LY_STMT_MODULE));
David Sedlák81497a32019-08-13 16:56:26 +02003511 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003512 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3513 LY_STMT_ANYXML, &mod->data, 0,
3514 LY_STMT_AUGMENT, &mod->augments, 0,
3515 LY_STMT_CHOICE, &mod->data, 0,
3516 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3517 LY_STMT_CONTAINER, &mod->data, 0,
3518 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3519 LY_STMT_DEVIATION, &mod->deviations, 0,
3520 LY_STMT_EXTENSION, &mod->extensions, 0,
3521 LY_STMT_FEATURE, &mod->features, 0,
3522 LY_STMT_GROUPING, &mod->groupings, 0,
3523 LY_STMT_IDENTITY, &mod->identities, 0,
3524 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3525 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3526 LY_STMT_LEAF, &mod->data, 0,
3527 LY_STMT_LEAF_LIST, &mod->data, 0,
3528 LY_STMT_LIST, &mod->data, 0,
3529 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3530 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3531 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3532 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3533 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3534 LY_STMT_REVISION, &mod->revs, 0,
3535 LY_STMT_RPC, &mod->rpcs, 0,
3536 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3537 LY_STMT_USES, &mod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003538 LY_STMT_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003539 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003540 ));
3541
Radek Krejcid6b76452019-09-03 17:03:03 +02003542 ret = yin_parse_content(ctx, subelems, 28, data, LY_STMT_MODULE, NULL, &mod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003543 subelems_deallocator(28, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003544 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003545
David Sedláked809f12019-09-13 10:15:11 +02003546 /* finalize parent pointers to the reallocated items */
3547 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
3548
3549 /* submodules share the namespace with the module names, so there must not be
3550 * a submodule of the same name in the context, no need for revision matching */
3551 dup = ly_ctx_get_submodule(ctx->xml_ctx.ctx, NULL, mod->mod->name, NULL);
3552 if (dup) {
3553 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
3554 return LY_EVALID;
3555 }
3556
3557 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003558}
3559
3560LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003561yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3562{
David Sedlák81497a32019-08-13 16:56:26 +02003563 LY_ERR ret = LY_SUCCESS;
3564 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003565 struct lysp_submodule *dup;
David Sedlák298ff6d2019-07-26 14:29:03 +02003566
Radek Krejcid6b76452019-09-03 17:03:03 +02003567 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, LY_STMT_SUBMODULE));
David Sedlák81497a32019-08-13 16:56:26 +02003568 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003569 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3570 LY_STMT_ANYXML, &submod->data, 0,
3571 LY_STMT_AUGMENT, &submod->augments, 0,
3572 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3573 LY_STMT_CHOICE, &submod->data, 0,
3574 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3575 LY_STMT_CONTAINER, &submod->data, 0,
3576 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3577 LY_STMT_DEVIATION, &submod->deviations, 0,
3578 LY_STMT_EXTENSION, &submod->extensions, 0,
3579 LY_STMT_FEATURE, &submod->features, 0,
3580 LY_STMT_GROUPING, &submod->groupings, 0,
3581 LY_STMT_IDENTITY, &submod->identities, 0,
3582 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3583 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3584 LY_STMT_LEAF, &submod->data, 0,
3585 LY_STMT_LEAF_LIST, &submod->data, 0,
3586 LY_STMT_LIST, &submod->data, 0,
3587 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3588 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3589 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3590 LY_STMT_REVISION, &submod->revs, 0,
3591 LY_STMT_RPC, &submod->rpcs, 0,
3592 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3593 LY_STMT_USES, &submod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003594 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003595 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003596 ));
3597
Radek Krejcid6b76452019-09-03 17:03:03 +02003598 ret = yin_parse_content(ctx, subelems, 27, data, LY_STMT_SUBMODULE, NULL, &submod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003599 subelems_deallocator(27, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003600 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003601
David Sedláked809f12019-09-13 10:15:11 +02003602 /* finalize parent pointers to the reallocated items */
3603 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
3604
3605 /* submodules share the namespace with the module names, so there must not be
3606 * a submodule of the same name in the context, no need for revision matching */
3607 dup = ly_ctx_get_submodule(ctx->xml_ctx.ctx, NULL, submod->name, NULL);
3608 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
3609 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
3610 return LY_EVALID;
3611 }
3612
3613 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003614}
3615
3616LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02003617yin_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 +02003618{
Radek Krejcid6b76452019-09-03 17:03:03 +02003619 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003620 LY_ERR ret = LY_SUCCESS;
3621 const char *prefix, *name;
3622 size_t prefix_len, name_len;
3623 struct yin_arg_record *attrs = NULL;
3624 struct lysp_submodule *mod_p = NULL;
3625
3626 /* create context */
3627 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003628 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003629 (*yin_ctx)->xml_ctx.ctx = ctx;
Radek Krejci12b1c152019-09-05 16:20:48 +02003630 (*yin_ctx)->pos_type = LY_VLOG_LINE;
David Sedlák8985a142019-07-31 16:43:06 +02003631 (*yin_ctx)->xml_ctx.line = 1;
3632
David Sedlák1b623122019-08-05 15:27:49 +02003633 /* map the typedefs and groupings list from main context to the submodule's context */
3634 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3635 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3636
David Sedlák8985a142019-07-31 16:43:06 +02003637 /* check submodule */
3638 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3639 LY_CHECK_GOTO(ret, cleanup);
3640 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3641 LY_CHECK_GOTO(ret, cleanup);
Radek Krejcid6b76452019-09-03 17:03:03 +02003642 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, LY_STMT_NONE);
David Sedlák8985a142019-07-31 16:43:06 +02003643
Radek Krejcid6b76452019-09-03 17:03:03 +02003644 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003645 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3646 ret = LY_EINVAL;
3647 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003648 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003649 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003650 ret = LY_EVALID;
3651 goto cleanup;
3652 }
3653
3654 mod_p = calloc(1, sizeof *mod_p);
3655 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3656 mod_p->parsing = 1;
3657
3658 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3659 LY_CHECK_GOTO(ret, cleanup);
3660
David Sedlák6d781b62019-08-02 15:22:52 +02003661 name = NULL;
David Sedlákbf8a2b72019-08-14 16:48:10 +02003662 /* skip possible trailing whitespaces at end of the input */
3663 while(*data && isspace(*data)) {
3664 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003665 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003666 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003667 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 +02003668 ret = LY_EVALID;
3669 goto cleanup;
3670 }
3671
David Sedlák8985a142019-07-31 16:43:06 +02003672 mod_p->parsing = 0;
3673 *submod = mod_p;
3674
3675cleanup:
3676 if (ret) {
3677 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003678 yin_parser_ctx_free(*yin_ctx);
3679 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003680 }
3681
3682 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3683 return ret;
3684}
3685
3686LY_ERR
3687yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003688{
David Sedláke4889912018-11-02 09:52:40 +01003689 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003690 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003691 struct lysp_module *mod_p = NULL;
3692 const char *prefix, *name;
3693 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003694 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003695
David Sedlák8985a142019-07-31 16:43:06 +02003696 /* create context */
3697 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003698 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003699 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
Radek Krejci335332a2019-09-05 13:03:35 +02003700 (*yin_ctx)->pos_type = LY_VLOG_LINE;
David Sedlák8985a142019-07-31 16:43:06 +02003701 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003702
David Sedlák8985a142019-07-31 16:43:06 +02003703 /* check module */
3704 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003705 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003706 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003707 LY_CHECK_GOTO(ret, cleanup);
Radek Krejcid6b76452019-09-03 17:03:03 +02003708 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, LY_STMT_NONE);
3709 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003710 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 +01003711 ret = LY_EINVAL;
3712 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003713 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003714 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003715 ret = LY_EVALID;
3716 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003717 }
3718
David Sedlák3017da42019-02-15 09:48:04 +01003719 /* allocate module */
3720 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003721 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003722 mod_p->mod = mod;
3723 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003724
David Sedlák00250342019-06-21 14:19:39 +02003725 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003726 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003727 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003728
David Sedlákbf8a2b72019-08-14 16:48:10 +02003729 name = NULL;
3730 /* skip possible trailing whitespaces at end of the input */
3731 while(*data && isspace(*data)) {
3732 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003733 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003734 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003735 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 +02003736 ret = LY_EVALID;
3737 goto cleanup;
3738 }
3739
David Sedlák3017da42019-02-15 09:48:04 +01003740 mod_p->parsing = 0;
3741 mod->parsed = mod_p;
3742
3743cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003744 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003745 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003746 yin_parser_ctx_free(*yin_ctx);
3747 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003748 }
David Sedlák8985a142019-07-31 16:43:06 +02003749 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003750 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003751}