blob: 1c2a9a8c0c9516d3432758e73d3829156871cddd [file] [log] [blame]
David Sedlákf824ad52018-10-14 23:58:15 +02001/**
2 * @file parser_yin.c
3 * @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
David Sedlák3b4db242018-10-19 16:11:01 +02004 * @brief YIN parser.
5 *
David Sedlákb1ce3f82019-06-05 14:37:26 +02006 * Copyright (c) 2015 - 2019 CESNET, z.s.p.o.
David Sedlák3b4db242018-10-19 16:11:01 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
David Sedlákf824ad52018-10-14 23:58:15 +020013 */
David Sedlákecf5eb82019-06-03 14:12:44 +020014#include "common.h"
15
David Sedlák3ffbc522019-07-02 17:49:28 +020016#include <assert.h>
David Sedlák3b4db242018-10-19 16:11:01 +020017#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
David Sedlák872c7b42018-10-26 13:15:20 +020020#include <string.h>
David Sedlákd6e56892019-07-01 15:40:24 +020021#include <stdbool.h>
David Sedlák5545f5d2019-07-11 11:55:16 +020022#include <errno.h>
David Sedlákf75d55e2019-07-12 16:52:50 +020023#include <ctype.h>
David Sedlák81497a32019-08-13 16:56:26 +020024#include <stdarg.h>
David Sedlákf824ad52018-10-14 23:58:15 +020025
David Sedlákf824ad52018-10-14 23:58:15 +020026#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020027#include "dict.h"
David Sedlák3b4db242018-10-19 16:11:01 +020028#include "xml.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020029#include "tree.h"
30#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020031#include "tree_schema_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020032#include "parser_yin.h"
David Sedlák00250342019-06-21 14:19:39 +020033
David Sedlák2b214ac2019-06-06 16:11:03 +020034/**
35 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020036 *
David Sedlák2b214ac2019-06-06 16:11:03 +020037 * @param ns Namespace URI to check.
38 *
39 * @return true if ns equals YIN_NS_URI false otherwise.
40 */
41#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
42
David Sedlákf6251182019-06-06 10:22:13 +020043const char *const yin_attr_list[] = {
44 [YIN_ARG_NAME] = "name",
45 [YIN_ARG_TARGET_NODE] = "target-node",
46 [YIN_ARG_MODULE] = "module",
47 [YIN_ARG_VALUE] = "value",
48 [YIN_ARG_TEXT] = "text",
49 [YIN_ARG_CONDITION] = "condition",
50 [YIN_ARG_URI] = "uri",
51 [YIN_ARG_DATE] = "date",
52 [YIN_ARG_TAG] = "tag",
David Sedlákf6251182019-06-06 10:22:13 +020053};
54
Radek Krejcid6b76452019-09-03 17:03:03 +020055enum ly_stmt
David Sedlákc1771b12019-07-10 15:55:46 +020056yin_match_keyword(struct yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejcid6b76452019-09-03 17:03:03 +020057 const char *prefix, size_t prefix_len, enum ly_stmt parrent)
David Sedlák1bccdfa2019-06-17 15:55:27 +020058{
David Sedlák8f7a1172019-06-20 14:42:18 +020059 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +020060 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020061 const struct lyxml_ns *ns = NULL;
62
63 if (!name || name_len == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +020064 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +020065 }
66
David Sedlákda8ffa32019-07-08 14:17:10 +020067 ns = lyxml_ns_get(&ctx->xml_ctx, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +020068 if (ns) {
69 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +020070 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +020071 }
72 } else {
73 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +020074 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020075 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020076
David Sedlák8f7a1172019-06-20 14:42:18 +020077 start = name;
78 kw = lysp_match_kw(NULL, &name);
79
80 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +020081 /* this is done because of collision in yang statement value and yang argument mapped to yin element value */
Radek Krejcid6b76452019-09-03 17:03:03 +020082 if (kw == LY_STMT_VALUE && parrent == LY_STMT_ERROR_MESSAGE) {
83 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +020084 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020085 return kw;
86 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020087 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +020088 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +020089 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +020090 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +020091 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020092 }
93}
94
David Sedlákc5b20842019-08-13 10:18:31 +020095enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +020096yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020097{
David Sedlákc5b20842019-08-13 10:18:31 +020098 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +020099 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200100 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200101
David Sedlák94de2aa2019-02-15 12:42:11 +0100102#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
103#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100104#define IF_ARG_PREFIX_END }
105
David Sedlák1c8b2702019-02-22 11:03:02 +0100106 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100107 case 'c':
108 already_read += 1;
109 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200110 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200111
David Sedlák94de2aa2019-02-15 12:42:11 +0100112 case 'd':
113 already_read += 1;
114 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200115 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200116
David Sedlák94de2aa2019-02-15 12:42:11 +0100117 case 'm':
118 already_read += 1;
119 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200120 break;
121
David Sedlák94de2aa2019-02-15 12:42:11 +0100122 case 'n':
123 already_read += 1;
124 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200125 break;
126
David Sedlák94de2aa2019-02-15 12:42:11 +0100127 case 't':
128 already_read += 1;
129 IF_ARG_PREFIX("a", 1)
130 IF_ARG("g", 1, YIN_ARG_TAG)
131 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
132 IF_ARG_PREFIX_END
133 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200134 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200135
David Sedlák94de2aa2019-02-15 12:42:11 +0100136 case 'u':
137 already_read += 1;
138 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200139 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200140
David Sedlák94de2aa2019-02-15 12:42:11 +0100141 case 'v':
142 already_read += 1;
143 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200144 break;
145 }
146
David Sedlákc10e7902018-12-17 02:17:59 +0100147 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200148 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200149 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200150 }
151
David Sedlák18730132019-03-15 15:51:34 +0100152#undef IF_ARG
153#undef IF_ARG_PREFIX
154#undef IF_ARG_PREFIX_END
155
David Sedlák872c7b42018-10-26 13:15:20 +0200156 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200157}
158
David Sedlák4f03b932019-07-26 13:01:47 +0200159void free_arg_rec(struct yin_parser_ctx *ctx, struct yin_arg_record *record) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200160 (void)ctx; /* unused */
David Sedlákd2d676a2019-07-22 11:28:19 +0200161 if (record && record->dynamic_content) {
David Sedlák00250342019-06-21 14:19:39 +0200162 free(record->content);
163 }
164}
165
Radek Krejcid6b76452019-09-03 17:03:03 +0200166#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
167 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
168 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
169 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200170
Radek Krejcid6b76452019-09-03 17:03:03 +0200171#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 +0200172
David Sedlák26ea1432019-08-14 13:42:23 +0200173/**
174 * @brief Free subelems information allocated on heap.
175 *
176 * @param[in] count Size of subelems array.
177 * @param[in] subelems Subelems array to free.
178 */
David Sedlák81497a32019-08-13 16:56:26 +0200179static void
180subelems_deallocator(size_t count, struct yin_subelement *subelems)
181{
182 for(size_t i = 0; i < count; ++i) {
183 if (HAS_META(subelems[i].type)) {
184 free(subelems[i].dest);
185 }
186 }
187
188 free(subelems);
189}
190
David Sedlák26ea1432019-08-14 13:42:23 +0200191/**
192 * @brief Allocate subelems information on heap.
193 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200194 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200195 * @param[in] count Number of subelements.
196 * @param[in] parent Parent node if any.
197 * @param[out] result Allocated subelems array.
198 *
199 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
200 */
David Sedlák81497a32019-08-13 16:56:26 +0200201static LY_ERR
202subelems_allocator(struct yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
203 struct yin_subelement **result, ...)
204{
205 va_list ap;
206
207 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200208 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200209
210 va_start(ap, result);
211 for (size_t i = 0; i < count; ++i) {
212 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200213 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200214 /* DEST */
215 if (IS_NODE_ELEM((*result)[i].type)) {
216 struct tree_node_meta *node_meta = NULL;
217 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200218 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200219 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200220 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200221 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200222 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200223 struct import_meta *imp_meta = NULL;
224 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200225 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200226 imp_meta->prefix = va_arg(ap, const char *);
227 imp_meta->imports = va_arg(ap, struct lysp_import **);
228 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200229 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200230 struct include_meta *inc_meta = NULL;
231 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200232 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200233 inc_meta->name = va_arg(ap, const char *);
234 inc_meta->includes = va_arg(ap, struct lysp_include **);
235 (*result)[i].dest = inc_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200236 } else if ((*result)[i].type == LY_STMT_INPUT || (*result)[i].type == LY_STMT_OUTPUT) {
David Sedlák81497a32019-08-13 16:56:26 +0200237 struct inout_meta *inout_meta = NULL;
238 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200239 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200240 inout_meta->parent = parent;
241 inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
242 (*result)[i].dest = inout_meta;
243 } else {
244 (*result)[i].dest = va_arg(ap, void *);
245 }
246 /* FLAGS */
247 (*result)[i].flags = va_arg(ap, int);
248 }
249 va_end(ap);
250
251 return LY_SUCCESS;
252
David Sedlákbf8a2b72019-08-14 16:48:10 +0200253mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200254 subelems_deallocator(count, *result);
255 LOGMEM(ctx->xml_ctx.ctx);
256 return LY_EMEM;
257}
258
David Sedlák8f7a1172019-06-20 14:42:18 +0200259LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200260yin_load_attributes(struct yin_parser_ctx *ctx, const char **data, struct yin_arg_record **attrs)
David Sedláka7406952019-04-05 10:33:07 +0200261{
262 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200263 struct yin_arg_record *argument_record = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +0200264 const char *prefix, *name;
265 size_t prefix_len, name_len;
David Sedláka7406952019-04-05 10:33:07 +0200266
David Sedlák555c7202019-07-04 12:14:12 +0200267 /* load all attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +0200268 while (ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákc5b20842019-08-13 10:18:31 +0200269 ret = lyxml_get_attribute(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák26ea1432019-08-14 13:42:23 +0200270 LY_CHECK_GOTO(ret, cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200271
David Sedlákda8ffa32019-07-08 14:17:10 +0200272 if (ctx->xml_ctx.status == LYXML_ATTR_CONTENT) {
273 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, *attrs, argument_record, ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +0200274 argument_record->name = name;
275 argument_record->name_len = name_len;
276 argument_record->prefix = prefix;
277 argument_record->prefix_len = prefix_len;
David Sedlákda8ffa32019-07-08 14:17:10 +0200278 ret = lyxml_get_string(&ctx->xml_ctx, data, &argument_record->content, &argument_record->content_len,
David Sedlák57715b12019-06-17 13:05:22 +0200279 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák26ea1432019-08-14 13:42:23 +0200280 LY_CHECK_GOTO(ret, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200281 }
282 }
283
David Sedlák8f7a1172019-06-20 14:42:18 +0200284cleanup:
285 if (ret != LY_SUCCESS) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200286 FREE_ARRAY(ctx, *attrs, free_arg_rec);
David Sedlákb4e44562019-07-04 15:42:12 +0200287 *attrs = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200288 }
289 return ret;
290}
291
David Sedlák4a650532019-07-10 11:55:18 +0200292LY_ERR
293yin_validate_value(struct yin_parser_ctx *ctx, enum yang_arg val_type, char *val, size_t len)
294{
295 int prefix = 0;
296 unsigned int c;
297 size_t utf8_char_len;
298 size_t already_read = 0;
299 while (already_read < len) {
300 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
301 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
302 already_read += utf8_char_len;
303 LY_CHECK_ERR_RET(already_read > len, LOGINT(ctx->xml_ctx.ctx), LY_EINT);
304
305 switch (val_type) {
306 case Y_IDENTIF_ARG:
307 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
308 break;
309 case Y_PREF_IDENTIF_ARG:
310 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
311 break;
312 case Y_STR_ARG:
313 case Y_MAYBE_STR_ARG:
314 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
315 break;
316 }
317 }
318
319 return LY_SUCCESS;
320}
321
David Sedlákb4e44562019-07-04 15:42:12 +0200322/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200323 * @brief Parse yin attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200324 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200325 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200326 * @param[in] attrs ([Sized array](@ref sizedarrays)) of attributes.
David Sedlák4a650532019-07-10 11:55:18 +0200327 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
328 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200329 * @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 +0200330 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200331 * @param[in] current_element Identification of current element, used for logging.
332 *
333 * @return LY_ERR values.
334 */
335static LY_ERR
David Sedlákc5b20842019-08-13 10:18:31 +0200336yin_parse_attribute(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, enum yin_argument arg_type,
Radek Krejcid6b76452019-09-03 17:03:03 +0200337 const char **arg_val, enum yang_arg val_type, enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200338{
David Sedlákc5b20842019-08-13 10:18:31 +0200339 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák8f7a1172019-06-20 14:42:18 +0200340 struct yin_arg_record *iter = NULL;
David Sedlák619db942019-07-03 14:47:30 +0200341 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200342
David Sedlák1bccdfa2019-06-17 15:55:27 +0200343 /* validation of attributes */
David Sedlák1f90d252019-07-10 17:09:32 +0200344 LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
David Sedlák00250342019-06-21 14:19:39 +0200345 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
346 if (!iter->prefix) {
David Sedlák060b00e2019-06-19 11:12:06 +0200347 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200348 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200349 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200350 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200351 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
David Sedlák292763b2019-07-09 11:10:53 +0200352 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200353 found = true;
David Sedlák4a650532019-07-10 11:55:18 +0200354 LY_CHECK_RET(yin_validate_value(ctx, val_type, iter->content, iter->content_len));
David Sedlák169cc522019-08-15 13:23:45 +0200355 INSERT_STRING(ctx->xml_ctx.ctx, *arg_val, iter->dynamic_content, iter->content, iter->content_len);
356 iter->dynamic_content = 0;
357 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200358 } else {
David Sedlák1538a842019-08-08 15:38:51 +0200359 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 +0200360 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200361 }
362 }
363 }
364
David Sedlák292763b2019-07-09 11:10:53 +0200365 /* anything else than Y_MAYBE_STR_ARG is mandatory */
366 if (val_type != Y_MAYBE_STR_ARG && !found) {
David Sedlák9c40a922019-07-08 17:04:43 +0200367 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 +0200368 return LY_EVALID;
369 }
370
371 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200372}
373
David Sedlákd6e56892019-07-01 15:40:24 +0200374/**
David Sedlákda8ffa32019-07-08 14:17:10 +0200375 * @brief Get record with given type. Array must be sorted in ascending order by array[n].type.
David Sedlákd6e56892019-07-01 15:40:24 +0200376 *
377 * @param[in] type Type of wanted record.
378 * @param[in] array_size Size of array.
379 * @param[in] array Searched array.
380 *
381 * @return Pointer to desired record on success, NULL if element is not in the array.
382 */
David Sedlákb4e44562019-07-04 15:42:12 +0200383static struct yin_subelement *
Radek Krejcid6b76452019-09-03 17:03:03 +0200384get_record(enum ly_stmt type, signed char array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200385{
David Sedlákb0faad82019-07-04 14:28:59 +0200386 signed char left = 0, right = array_size - 1, middle;
387
388 while (left <= right) {
389 middle = left + (right - left) / 2;
390
391 if (array[middle].type == type) {
392 return &array[middle];
393 }
394
395 if (array[middle].type < type) {
396 left = middle + 1;
397 } else {
398 right = middle - 1;
David Sedlákd6e56892019-07-01 15:40:24 +0200399 }
400 }
401
402 return NULL;
403}
404
David Sedlákbba38e52019-07-09 15:20:01 +0200405/**
406 * @brief Helper function to check mandatory constraint of subelement.
407 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200408 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200409 * @param[in] subelem_info Array of information about subelements.
410 * @param[in] subelem_info_size Size of subelem_info array.
411 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
412 *
413 * @return LY_ERR values.
414 */
415static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200416yin_check_subelem_mandatory_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200417 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200418{
David Sedlákb0faad82019-07-04 14:28:59 +0200419 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200420 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
David Sedlák21f87cd2019-07-03 16:53:23 +0200421 if (subelem_info[i].flags & YIN_SUBELEM_MANDATORY && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200422 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200423 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200424 return LY_EVALID;
425 }
426 }
427
428 return LY_SUCCESS;
429}
430
David Sedlákbba38e52019-07-09 15:20:01 +0200431/**
432 * @brief Helper function to check "first" constraint of subelement.
433 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200434 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200435 * @param[in] subelem_info Array of information about subelements.
436 * @param[in] subelem_info_size Size of subelem_info array.
437 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200438 * @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 +0200439 *
440 * @return LY_ERR values.
441 */
442static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200443yin_check_subelem_first_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200444 signed char subelem_info_size, enum ly_stmt current_element,
David Sedláke1a30302019-07-10 13:49:38 +0200445 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200446{
David Sedlákb0faad82019-07-04 14:28:59 +0200447 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200448 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200449 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
450 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200451 return LY_EVALID;
452 }
453 }
454
455 return LY_SUCCESS;
456}
457
David Sedlákbba38e52019-07-09 15:20:01 +0200458/**
459 * @brief Helper function to check if array of information about subelements is in ascending order.
460 *
461 * @param[in] subelem_info Array of information about subelements.
462 * @param[in] subelem_info_size Size of subelem_info array.
463 *
464 * @return True iff subelem_info array is in ascending order, False otherwise.
465 */
David Sedlák5545f5d2019-07-11 11:55:16 +0200466#ifndef NDEBUG
David Sedlákbba38e52019-07-09 15:20:01 +0200467static bool
David Sedlákb0faad82019-07-04 14:28:59 +0200468is_ordered(struct yin_subelement *subelem_info, signed char subelem_info_size)
469{
Radek Krejcid6b76452019-09-03 17:03:03 +0200470 enum ly_stmt current = LY_STMT_NONE; /* 0 (minimal value) */
David Sedlákb0faad82019-07-04 14:28:59 +0200471
472 for (signed char i = 0; i < subelem_info_size; ++i) {
473 if (subelem_info[i].type <= current) {
474 return false;
475 }
476 current = subelem_info[i].type;
477 }
478
479 return true;
480}
David Sedlák5545f5d2019-07-11 11:55:16 +0200481#endif
David Sedlákb0faad82019-07-04 14:28:59 +0200482
David Sedlákd6e56892019-07-01 15:40:24 +0200483/**
David Sedlákb4e44562019-07-04 15:42:12 +0200484 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
485 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200486 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200487 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200488 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákd6e56892019-07-01 15:40:24 +0200489 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákb4e44562019-07-04 15:42:12 +0200490 * @param[in] kw Type of current element.
491 * @param[out] value Where value of attribute should be stored.
492 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200493 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200494 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200495 *
David Sedlákd6e56892019-07-01 15:40:24 +0200496 * @return LY_ERR values.
497 */
David Sedlákb4e44562019-07-04 15:42:12 +0200498static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200499yin_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 +0200500 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 +0200501{
David Sedlák1f90d252019-07-10 17:09:32 +0200502 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200503 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200504 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200505 };
David Sedlákb4e44562019-07-04 15:42:12 +0200506
David Sedlákda8ffa32019-07-08 14:17:10 +0200507 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200508}
509
510/**
David Sedlák6542aed2019-08-14 10:47:43 +0200511 * @brief Parse path element.
512 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200513 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200514 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
515 * @param[in,out] data Data to read from, always moved to currently handled character.
516 * @param[in] kw Type of current element.
517 * @param[out] type Type structure to store parsed value, flags and extension instances.
518 *
519 * @return LY_ERR values.
520 */
521static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200522yin_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 +0200523 struct lysp_type *type)
524{
525 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
526 YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
527 type->flags |= LYS_SET_PATH;
528
529 return LY_SUCCESS;
530}
531
532/**
David Sedlákd3983112019-07-12 11:20:56 +0200533 * @brief Parse pattern element.
534 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200535 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd3983112019-07-12 11:20:56 +0200536 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
537 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200538 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200539 *
540 * @return LY_ERR values.
541 */
542static LY_ERR
543yin_parse_pattern(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
544 struct lysp_type *type)
545{
546 const char *real_value = NULL;
547 char *saved_value = NULL;
548 struct lysp_restr *restr;
549
550 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->patterns, restr, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200551 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 +0200552 size_t len = strlen(real_value);
553
554 saved_value = malloc(len + 2);
555 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
556 memmove(saved_value + 1, real_value, len);
557 FREE_STRING(ctx->xml_ctx.ctx, real_value);
558 saved_value[0] = 0x06;
559 saved_value[len + 1] = '\0';
560 restr->arg = lydict_insert_zc(ctx->xml_ctx.ctx, saved_value);
561 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
562 type->flags |= LYS_SET_PATTERN;
563
564 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200565 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
566 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
567 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
568 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
569 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
570 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákd3983112019-07-12 11:20:56 +0200571 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200572 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200573}
574
David Sedlákc5b20842019-08-13 10:18:31 +0200575/**
576 * @brief Parse fraction-digits element.
577 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200578 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200579 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
580 * @param[in,out] data Data to read from, always moved to currently handled character.
581 * @param[in,out] type Type structure to store value, flags and extension instances.
582 *
583 * @return LY_ERR values.
584 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200585static LY_ERR
586yin_parse_fracdigits(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
587 struct lysp_type *type)
588{
589 const char *temp_val = NULL;
590 char *ptr;
591 unsigned long int num;
592
Radek Krejcid6b76452019-09-03 17:03:03 +0200593 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 +0200594
595 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200596 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200597 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
598 return LY_EVALID;
599 }
600
601 errno = 0;
602 num = strtoul(temp_val, &ptr, 10);
603 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200604 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200605 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
606 return LY_EVALID;
607 }
608 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200609 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200610 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
611 return LY_EVALID;
612 }
David Sedlák2ab5d8e2019-07-16 11:19:41 +0200613 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200614 type->fraction_digits = num;
615 type->flags |= LYS_SET_FRDIGITS;
616 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200617 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200618 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200619 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200620}
621
David Sedlák07869a52019-07-12 14:28:19 +0200622/**
David Sedlák43801c92019-08-05 15:58:54 +0200623 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200624 *
625 * @param[in,out] ctx YIN parser context for logging and to store current state.
626 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
627 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200628 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200629 *
630 * @return LY_ERR values.
631 */
David Sedlákca36c422019-07-12 12:47:55 +0200632static LY_ERR
David Sedlák43801c92019-08-05 15:58:54 +0200633yin_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 +0200634{
David Sedlák07869a52019-07-12 14:28:19 +0200635 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200636
David Sedlák43801c92019-08-05 15:58:54 +0200637 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->enums, en, LY_EMEM);
638 type->flags |= LYS_SET_ENUM;
Radek Krejcid6b76452019-09-03 17:03:03 +0200639 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, LY_STMT_ENUM));
David Sedlák43801c92019-08-05 15:58:54 +0200640 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
641 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
642 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200643
644 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200645 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
646 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
647 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
648 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
649 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
650 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákca36c422019-07-12 12:47:55 +0200651 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200652 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200653}
654
655/**
656 * @brief Parse bit element.
657 *
658 * @param[in,out] ctx YIN parser context for logging and to store current state.
659 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
660 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200661 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200662 *
663 * @return LY_ERR values.
664 */
665static LY_ERR
666yin_parse_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
667 struct lysp_type *type)
668{
669 struct lysp_type_enum *en;
670
671 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->bits, en, LY_EMEM);
672 type->flags |= LYS_SET_BIT;
Radek Krejcid6b76452019-09-03 17:03:03 +0200673 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 +0200674 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
675
676 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200677 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
678 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
679 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
680 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
681 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
682 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák43801c92019-08-05 15:58:54 +0200683 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200684 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200685}
686
David Sedlákd3983112019-07-12 11:20:56 +0200687/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200688 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
689 * more instances, such as base or if-feature.
690 *
691 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200692 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200693 * @param[in,out] data Data to read from, always moved to currently handled character.
694 * @param[in] kw Type of current element.
695 * @param[out] values Parsed values to add to.
696 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200697 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200698 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200699 *
700 * @return LY_ERR values.
701 */
702static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200703yin_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 +0200704 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 +0200705{
706 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200707 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200708 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200709 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200710 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200711 };
712
David Sedlák1f90d252019-07-10 17:09:32 +0200713 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200714
715 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
716}
717
718/**
David Sedlák6542aed2019-08-14 10:47:43 +0200719 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
720 *
721 * @param[in,out] ctx YIN parser context for logging and to store current state.
722 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
723 * @param[in,out] data Data to read from, always moved to currently handled character.
724 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200725 * @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 +0200726 * @param[in] arg_type Expected type of attribute.
727 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200728 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200729 *
730 * @return LY_ERR values.
731 */
732static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200733yin_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 +0200734 struct yin_subelement *subinfo, enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
735{
736 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
737 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subinfo->dest,
738 arg_type, arg_val_type, exts));
739 } else {
740 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subinfo->dest,
741 arg_type, arg_val_type, exts));
742 }
743
744 return LY_SUCCESS;
745}
746
747/**
748 * @brief Parse base element.
749 *
750 * @param[in,out] ctx YIN parser context for logging and to store current state.
751 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
752 * @param[in,out] data Data to read from, always moved to currently handled character.
753 * @param[in] parent Identification of parent element.
754 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200755 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200756 *
757 * @return LY_ERR values.
758 */
759static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200760yin_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 +0200761 void *dest, struct lysp_ext_instance **exts)
762{
763 struct lysp_type *type = NULL;
764
Radek Krejcid6b76452019-09-03 17:03:03 +0200765 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200766 type = (struct lysp_type *)dest;
Radek Krejcid6b76452019-09-03 17:03:03 +0200767 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 +0200768 Y_PREF_IDENTIF_ARG, exts));
769 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200770 } else if (parent == LY_STMT_IDENTITY) {
771 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, LY_STMT_BASE, (const char ***)dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200772 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
773 } else {
774 LOGINT(ctx->xml_ctx.ctx);
775 return LY_EINT;
776 }
777
778 return LY_SUCCESS;
779}
780
781/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200782 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200783 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200784 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákcf5569a2019-07-11 13:31:34 +0200785 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
786 * @param[in,out] data Data to read from, always moved to currently handled character.
787 * @prama[out] type Type structure to store value, flag and extensions.
788 *
789 * @return LY_ERR values.
790 */
791static LY_ERR
792yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
793 const char **data, struct lysp_type *type)
794{
795 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200796 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200797 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200798 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200799
800 type->flags |= LYS_SET_REQINST;
Radek Krejcid6b76452019-09-03 17:03:03 +0200801 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 +0200802 if (strcmp(temp_val, "true") == 0) {
803 type->require_instance = 1;
804 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200805 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
806 "require-instance", "true", "false");
David Sedlákcf5569a2019-07-11 13:31:34 +0200807 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
808 return LY_EVALID;
809 }
810 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
811
Radek Krejcid6b76452019-09-03 17:03:03 +0200812 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200813}
814
815/**
David Sedlákce77bf52019-07-11 16:59:31 +0200816 * @brief Parse modifier element.
817 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200818 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200819 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
820 * @param[in,out] data Data to read from, always moved to currently handled character.
821 * @param[in,out] pat Value to write to.
822 * @param[in,out] exts Extension instances to add to.
823 *
824 * @return LY_ERR values.
825 */
826static LY_ERR
827yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
828 const char **pat, struct lysp_ext_instance **exts)
829{
David Sedlákd3983112019-07-12 11:20:56 +0200830 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200831 const char *temp_val;
832 char *modified_val;
833 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200834 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákce77bf52019-07-11 16:59:31 +0200835 };
836
Radek Krejcid6b76452019-09-03 17:03:03 +0200837 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 +0200838 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200839 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
840 "modifier", "invert-match");
David Sedlákce77bf52019-07-11 16:59:31 +0200841 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
842 return LY_EVALID;
843 }
David Sedlákd3983112019-07-12 11:20:56 +0200844 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200845
846 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200847 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200848 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200849 strcpy(modified_val, *pat);
850 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200851
852 /* modify the new value */
853 modified_val[0] = 0x15;
854 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
855
Radek Krejcid6b76452019-09-03 17:03:03 +0200856 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200857}
858
859/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200860 * @brief Parse a restriction element (length, range or one instance of must).
861 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200862 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb7296dd2019-07-11 14:58:38 +0200863 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
864 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejcid6b76452019-09-03 17:03:03 +0200865 * @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 +0200866 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200867 */
868static LY_ERR
869yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +0200870 enum ly_stmt restr_kw, struct lysp_restr *restr)
David Sedlákb7296dd2019-07-11 14:58:38 +0200871{
Radek Krejcid6b76452019-09-03 17:03:03 +0200872 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
David Sedlákb7296dd2019-07-11 14:58:38 +0200873 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200874 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
875 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
876 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
877 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
878 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200879 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200880 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200881 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200882 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
883
884 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
885}
886
887/**
David Sedlák6542aed2019-08-14 10:47:43 +0200888 * @brief Parse range element.
889 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200890 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200891 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
892 * @param[in,out] data Data to read from, always moved to currently handled character.
893 * @param[out] type Type structure to store parsed value and flags.
894 *
895 * @return LY_ERR values.
896 */
897static LY_ERR
898yin_parse_range(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
899 const char **data, struct lysp_type *type)
900{
901 type->range = calloc(1, sizeof *type->range);
902 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200903 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, LY_STMT_RANGE, type->range));
David Sedlák6542aed2019-08-14 10:47:43 +0200904 type->flags |= LYS_SET_RANGE;
905
906 return LY_SUCCESS;
907}
908
909/**
910 * @brief Parse length element.
911 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200912 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200913 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
914 * @param[in,out] data Data to read from, always moved to currently handled character.
915 * @param[out] type Type structure to store parsed value and flags.
916 *
917 * @return LY_ERR values.
918 */
919static LY_ERR
920yin_parse_length(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
921 const char **data, struct lysp_type *type)
922{
923 type->length = calloc(1, sizeof *type->length);
924 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200925 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200926 type->flags |= LYS_SET_LENGTH;
927
928 return LY_SUCCESS;
929}
930
931/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200932 * @brief Parse must element.
933 *
934 * @param[in,out] ctx YIN parser context for logging and to store current state.
935 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
936 * @param[in,out] data Data to read from, always moved to currently handled character.
937 * @param[in,out] restrs Restrictions to add to.
938 *
939 * @return LY_ERR values.
940 */
941static LY_ERR
942yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
943{
944 struct lysp_restr *restr;
945
946 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200947 return yin_parse_restriction(ctx, attrs, data, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200948}
949
950/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200951 * @brief Parse position or value element.
952 *
953 * @param[in,out] ctx YIN parser context for logging and to store current state.
954 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
955 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejcid6b76452019-09-03 17:03:03 +0200956 * @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 +0200957 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200958 *
959 * @return LY_ERR values.
960 */
961static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +0200962yin_parse_value_pos(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +0200963 enum ly_stmt kw, struct lysp_type_enum *enm)
David Sedlák5545f5d2019-07-11 11:55:16 +0200964{
Radek Krejcid6b76452019-09-03 17:03:03 +0200965 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +0200966 const char *temp_val = NULL;
967 char *ptr;
968 long int num;
969 unsigned long int unum;
970
971 /* set value flag */
972 enm->flags |= LYS_SET_VALUE;
973
974 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200975 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 +0200976 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
Radek Krejcid6b76452019-09-03 17:03:03 +0200977 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200978 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 +0200979 goto error;
980 }
981
982 /* convert value */
983 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +0200984 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200985 num = strtol(temp_val, &ptr, 10);
986 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200987 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 +0200988 goto error;
989 }
990 } else {
991 unum = strtoul(temp_val, &ptr, 10);
992 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200993 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 +0200994 goto error;
995 }
996 }
997 /* check if whole argument value was converted */
998 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200999 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 +02001000 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +02001001 }
1002 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +02001003 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 +02001004 goto error;
1005 }
1006 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001007 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +02001008 enm->value = num;
1009 } else {
1010 enm->value = unum;
1011 }
1012 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1013
1014 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +02001015 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001016 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +02001017 };
David Sedlák5545f5d2019-07-11 11:55:16 +02001018 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
1019
David Sedlákbf8a2b72019-08-14 16:48:10 +02001020error:
David Sedlák5545f5d2019-07-11 11:55:16 +02001021 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1022 return LY_EVALID;
1023}
1024
David Sedlák05404f62019-07-24 14:11:53 +02001025
1026/**
1027 * @brief Parse belongs-to element.
1028 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001029 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001030 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1031 * @param[in,out] data Data to read from, always moved to currently handled character.
1032 * @param[out] submod Structure of submodule that is being parsed.
1033 * @param[in,out] exts Extension instances to add to.
1034 *
1035 * @return LY_ERR values
1036 */
1037static LY_ERR
1038yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1039 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
1040{
1041 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001042 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1043 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák05404f62019-07-24 14:11:53 +02001044 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001045 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 +02001046
Radek Krejcid6b76452019-09-03 17:03:03 +02001047 return yin_parse_content(ctx, subelems, 2, data, LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001048}
1049
David Sedlák5545f5d2019-07-11 11:55:16 +02001050/**
David Sedlákc1771b12019-07-10 15:55:46 +02001051 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001052 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001053 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001054 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001055 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákcf5569a2019-07-11 13:31:34 +02001056 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejcid6b76452019-09-03 17:03:03 +02001057 * @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 +02001058 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001059 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001060 *
1061 * @return LY_ERR values.
1062 */
1063static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001064yin_parse_meta(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001065 enum ly_stmt elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +02001066{
Radek Krejcid6b76452019-09-03 17:03:03 +02001067 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 +02001068
David Sedlák968ac342019-07-11 15:17:59 +02001069 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001070 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1071 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +02001072 };
David Sedlákdf2a9732019-08-07 13:23:16 +02001073 /* check attributes */
1074 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 +02001075
David Sedlákdf2a9732019-08-07 13:23:16 +02001076 /* parse content */
David Sedlákda8ffa32019-07-08 14:17:10 +02001077 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001078}
1079
1080/**
David Sedlákc1771b12019-07-10 15:55:46 +02001081 * @brief Parse error-message element.
1082 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001083 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001084 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákc1771b12019-07-10 15:55:46 +02001085 * @param[in,out] data Data to read from.
1086 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001087 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001088 *
1089 * @return LY_ERR values.
1090 */
1091static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001092yin_parse_err_msg(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdf2a9732019-08-07 13:23:16 +02001093 const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +02001094{
David Sedlák968ac342019-07-11 15:17:59 +02001095 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001096 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1097 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +02001098 };
David Sedlákc1771b12019-07-10 15:55:46 +02001099
David Sedlákdf2a9732019-08-07 13:23:16 +02001100 /* check attributes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001101 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 +02001102
Radek Krejcid6b76452019-09-03 17:03:03 +02001103 return yin_parse_content(ctx, subelems, 2, data, LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001104}
1105
1106/**
David Sedlák6542aed2019-08-14 10:47:43 +02001107 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001108 *
1109 * @param[in,out] ctx YIN parser context for logging and to store current state.
1110 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1111 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák6542aed2019-08-14 10:47:43 +02001112 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001113 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001114 *
1115 * @return LY_ERR values.
1116 */
1117static LY_ERR
David Sedlák6542aed2019-08-14 10:47:43 +02001118yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001119 enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001120{
David Sedlák6542aed2019-08-14 10:47:43 +02001121 struct lysp_type *type = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +02001122 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001123 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
1124 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1125 type = *((struct lysp_type **)subinfo->dest);
1126 } else {
1127 type = (struct lysp_type *)subinfo->dest;
1128 }
1129 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001130 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001131 struct lysp_type *nested_type = NULL;
1132 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->types, nested_type, LY_EMEM);
1133 type->flags |= LYS_SET_TYPE;
1134 type = nested_type;
1135 }
David Sedlák374d2b32019-07-17 15:06:55 +02001136 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001137 {LY_STMT_BASE, type, 0},
1138 {LY_STMT_BIT, type, 0},
1139 {LY_STMT_ENUM, type, 0},
1140 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1141 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1142 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1143 {LY_STMT_PATTERN, type, 0},
1144 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1145 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1146 {LY_STMT_TYPE, type},
1147 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák374d2b32019-07-17 15:06:55 +02001148 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001149 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1150 return yin_parse_content(ctx, subelems, 11, data, LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001151}
1152
David Sedlák1af868e2019-07-17 17:03:14 +02001153/**
1154 * @brief Parse max-elements element.
1155 *
1156 * @param[in,out] ctx YIN parser context for logging and to store current state.
1157 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1158 * @param[in,out] data Data to read from, always moved to currently handled character.
1159 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001160 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001161 * @param[in,out] exts Extension instances to add to.
1162 *
1163 * @return LY_ERR values.
1164 */
1165static LY_ERR
1166yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
1167 uint16_t *flags, struct lysp_ext_instance **exts)
1168{
1169 const char *temp_val = NULL;
1170 char *ptr;
1171 unsigned long int num;
1172 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001173 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák1af868e2019-07-17 17:03:14 +02001174 };
David Sedlák374d2b32019-07-17 15:06:55 +02001175
David Sedlák1af868e2019-07-17 17:03:14 +02001176 *flags |= LYS_SET_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02001177 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 +02001178 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 +02001179 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001180 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1181 return LY_EVALID;
1182 }
1183
1184 if (strcmp(temp_val, "unbounded")) {
1185 errno = 0;
1186 num = strtoul(temp_val, &ptr, 10);
1187 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001188 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001189 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1190 return LY_EVALID;
1191 }
1192 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001193 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001194 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1195 return LY_EVALID;
1196 }
1197 *max = num;
1198 }
1199 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
Radek Krejcid6b76452019-09-03 17:03:03 +02001200 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001201}
David Sedlák374d2b32019-07-17 15:06:55 +02001202
1203/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001204 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001205 *
1206 * @param[in,out] ctx YIN parser context for logging and to store current state.
1207 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1208 * @param[in,out] data Data to read from, always moved to currently handled character.
1209 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001210 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001211 * @param[in,out] exts Extension instances to add to.
1212 *
1213 * @return LY_ERR values.
1214 */
1215static LY_ERR
1216yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
1217 uint16_t *flags, struct lysp_ext_instance **exts)
1218{
1219 const char *temp_val = NULL;
1220 char *ptr;
1221 unsigned long int num;
1222 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001223 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák09e18c92019-07-18 11:17:11 +02001224 };
1225
1226 *flags |= LYS_SET_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02001227 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 +02001228
1229 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001230 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001231 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1232 return LY_EVALID;
1233 }
1234
1235 errno = 0;
1236 num = strtoul(temp_val, &ptr, 10);
1237 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001238 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001239 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1240 return LY_EVALID;
1241 }
1242 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001243 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001244 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1245 return LY_EVALID;
1246 }
1247 *min = num;
1248 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
Radek Krejcid6b76452019-09-03 17:03:03 +02001249 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001250}
1251
David Sedláka2dad212019-07-18 12:45:19 +02001252/**
1253 * @brief Parse min-elements or max-elements element.
1254 *
1255 * @param[in,out] ctx YIN parser context for logging and to store current state.
1256 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1257 * @param[in,out] data Data to read from, always moved to currently handled character.
1258 * @param[in] parent Identification of parent element.
1259 * @param[in] current Identification of current element.
1260 * @param[in] dest Where the parsed value and flags should be stored.
1261 *
1262 * @return LY_ERR values.
1263 */
David Sedlák09e18c92019-07-18 11:17:11 +02001264static LY_ERR
1265yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001266 enum ly_stmt parent, enum ly_stmt current, void *dest)
David Sedlák09e18c92019-07-18 11:17:11 +02001267{
Radek Krejcid6b76452019-09-03 17:03:03 +02001268 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1269 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 +02001270 uint32_t *lim;
1271 uint16_t *flags;
1272 struct lysp_ext_instance **exts;
1273
Radek Krejcid6b76452019-09-03 17:03:03 +02001274 if (parent == LY_STMT_LEAF_LIST) {
1275 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 +02001276 flags = &((struct lysp_node_leaflist *)dest)->flags;
1277 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001278 } else if (parent == LY_STMT_REFINE) {
1279 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001280 flags = &((struct lysp_refine *)dest)->flags;
1281 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001282 } else if (parent == LY_STMT_LIST) {
1283 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 +02001284 flags = &((struct lysp_node_list *)dest)->flags;
1285 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001286 } else {
1287 lim = ((struct minmax_dev_meta *)dest)->lim;
1288 flags = ((struct minmax_dev_meta *)dest)->flags;
1289 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001290 }
1291
Radek Krejcid6b76452019-09-03 17:03:03 +02001292 if (current == LY_STMT_MAX_ELEMENTS) {
David Sedlák09e18c92019-07-18 11:17:11 +02001293 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1294 } else {
1295 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1296 }
1297
1298 return LY_SUCCESS;
1299}
1300
1301/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001302 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001303 *
1304 * @param[in,out] ctx YIN parser context for logging and to store current state.
1305 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1306 * @param[in,out] data Data to read from, always moved to currently handled character.
1307 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001308 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001309 *
1310 * @return LY_ERR values.
1311 */
1312static LY_ERR
1313yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1314 uint16_t *flags, struct lysp_ext_instance **exts)
1315{
1316 const char *temp_val;
1317 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001318 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedláka2dad212019-07-18 12:45:19 +02001319 };
1320
Radek Krejcid6b76452019-09-03 17:03:03 +02001321 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 +02001322 if (strcmp(temp_val, "system") == 0) {
1323 *flags |= LYS_ORDBY_SYSTEM;
1324 } else if (strcmp(temp_val, "user") == 0) {
1325 *flags |= LYS_ORDBY_USER;
1326 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001327 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1328 "ordered-by", "system", "user");
David Sedláka2dad212019-07-18 12:45:19 +02001329 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1330 return LY_EVALID;
1331 }
1332 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1333
Radek Krejcid6b76452019-09-03 17:03:03 +02001334 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001335}
1336
1337/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001338 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001339 *
1340 * @param[in,out] ctx YIN parser context for logging and to store current state.
1341 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1342 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejcid6b76452019-09-03 17:03:03 +02001343 * @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 +02001344 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001345 *
1346 * @return LY_ERR values.
1347 */
1348static LY_ERR
1349yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001350 enum ly_stmt any_kw, struct tree_node_meta *node_meta)
David Sedlák8a83bbb2019-07-18 14:46:00 +02001351{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001352 struct lysp_node_anydata *any;
1353
David Sedlák8d552d62019-08-06 15:29:05 +02001354 /* create new sibling */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001355 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, any, next);
Radek Krejcid6b76452019-09-03 17:03:03 +02001356 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001357 any->parent = node_meta->parent;
1358
David Sedlákbf8a2b72019-08-14 16:48:10 +02001359 /* parse argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001360 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 +02001361
1362 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001363 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1364 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1365 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1366 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1367 {LY_STMT_MUST, &any->musts, 0},
1368 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1369 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1370 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1371 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8a83bbb2019-07-18 14:46:00 +02001372 };
1373 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1374}
1375
1376/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001377 * @brief parse leaf element.
1378 *
1379 * @param[in,out] ctx YIN parser context for logging and to store current state.
1380 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1381 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001382 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001383 *
1384 * @return LY_ERR values.
1385 */
1386static LY_ERR
1387yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1388 struct tree_node_meta *node_meta)
1389{
David Sedlák203ca3a2019-07-18 15:26:25 +02001390 struct lysp_node_leaf *leaf;
1391
David Sedlák8d552d62019-08-06 15:29:05 +02001392 /* create structure new leaf */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001393 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, leaf, next);
David Sedlák203ca3a2019-07-18 15:26:25 +02001394 leaf->nodetype = LYS_LEAF;
1395 leaf->parent = node_meta->parent;
1396
David Sedlák203ca3a2019-07-18 15:26:25 +02001397 /* parser argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001398 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 +02001399
1400 /* parse content */
1401 struct yin_subelement subelems[12] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001402 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1403 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1404 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1405 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1406 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1407 {LY_STMT_MUST, &leaf->musts, 0},
1408 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1409 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1410 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1411 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1412 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1413 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001414 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001415 return yin_parse_content(ctx, subelems, 12, data, LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001416}
1417
1418/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001419 * @brief Parse leaf-list element.
1420 *
1421 * @param[in,out] ctx YIN parser context for logging and to store current state.
1422 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1423 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001424 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001425 *
1426 * @return LY_ERR values.
1427 */
1428static LY_ERR
1429yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1430 struct tree_node_meta *node_meta)
1431{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001432 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001433
David Sedlákbf8a2b72019-08-14 16:48:10 +02001434 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, llist, next);
David Sedlák8d552d62019-08-06 15:29:05 +02001435
David Sedlákc3da3ef2019-07-19 12:56:08 +02001436 llist->nodetype = LYS_LEAFLIST;
1437 llist->parent = node_meta->parent;
1438
David Sedlákc3da3ef2019-07-19 12:56:08 +02001439 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001440 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 +02001441
1442 /* parse content */
1443 struct yin_subelement subelems[14] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001444 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1445 {LY_STMT_DEFAULT, &llist->dflts, 0},
1446 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1447 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1448 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1449 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1450 {LY_STMT_MUST, &llist->musts, 0},
1451 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1452 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1453 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1454 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1455 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1456 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1457 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001458 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001459 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 +02001460
David Sedlákbf8a2b72019-08-14 16:48:10 +02001461 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001462 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001463 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001464 return LY_EVALID;
1465 }
1466 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001467 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001468 return LY_EVALID;
1469 }
1470
1471 return LY_SUCCESS;
1472}
1473
1474/**
David Sedlák04e17b22019-07-19 15:29:48 +02001475 * @brief Parse typedef element.
1476 *
1477 * @param[in,out] ctx YIN parser context for logging and to store current state.
1478 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1479 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001480 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001481 *
1482 * @return LY_ERR values.
1483 */
1484static LY_ERR
1485yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02001486 struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001487{
1488 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001489 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
David Sedlák6881b512019-08-13 12:52:00 +02001490 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001491
1492 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001493 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 +02001494
1495 /* parse content */
1496 struct yin_subelement subelems[7] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001497 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1498 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1499 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1500 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1501 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1502 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1503 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001504 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001505 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001506
1507 /* store data for collision check */
1508 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
David Sedláke8b74df2019-08-14 14:18:22 +02001509 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0) == -1, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001510 }
1511
1512 return LY_SUCCESS;
1513}
1514
1515/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001516 * @brief Parse refine element.
1517 *
1518 * @param[in,out] ctx YIN parser context for logging and to store current state.
1519 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1520 * @param[in,out] data Data to read from, always moved to currently handled character.
1521 * @param[in,out] refines Refines to add to.
1522 *
1523 * @return LY_ERR values.
1524 */
1525static LY_ERR
1526yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1527 struct lysp_refine **refines)
1528{
1529 struct lysp_refine *rf;
1530
1531 /* allocate new refine */
1532 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1533
1534 /* parse attribute */
Radek Krejcid6b76452019-09-03 17:03:03 +02001535 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 +02001536 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1537
1538 /* parse content */
1539 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001540 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1541 {LY_STMT_DEFAULT, &rf->dflts, 0},
1542 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1543 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
1544 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1545 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1546 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1547 {LY_STMT_MUST, &rf->musts, 0},
1548 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1549 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1550 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001551 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001552 return yin_parse_content(ctx, subelems, 11, data, LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001553}
1554
1555/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001556 * @brief Parse uses element.
1557 *
1558 * @param[in,out] ctx YIN parser context for logging and to store current state.
1559 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1560 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001561 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001562 *
1563 * @return LY_ERR values.
1564 */
1565static LY_ERR
1566yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1567 struct tree_node_meta *node_meta)
1568{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001569 struct lysp_node_uses *uses;
1570
David Sedlák8d552d62019-08-06 15:29:05 +02001571 /* create new uses */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001572 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, uses, next);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001573 uses->nodetype = LYS_USES;
1574 uses->parent = node_meta->parent;
1575
David Sedlák0d6de5a2019-07-22 13:25:44 +02001576 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001577 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 +02001578
1579 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001580 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001581 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001582 {LY_STMT_AUGMENT, &augments, 0},
1583 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1584 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1585 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1586 {LY_STMT_REFINE, &uses->refines, 0},
1587 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1588 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1589 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001590 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001591 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001592 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1593
1594 return LY_SUCCESS;
1595}
1596
1597/**
David Sedlákaa854b02019-07-22 14:17:10 +02001598 * @brief Parse revision element.
1599 *
1600 * @param[in,out] ctx YIN parser context for logging and to store current state.
1601 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1602 * @param[in,out] data Data to read from, always moved to currently handled character.
1603 * @param[in,out] revs Parsed revisions to add to.
1604 *
1605 * @return LY_ERR values.
1606 */
1607static LY_ERR
1608yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1609 struct lysp_revision **revs)
1610{
1611 struct lysp_revision *rev;
1612 const char *temp_date = NULL;
1613
1614 /* allocate new reivison */
1615 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1616
1617 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001618 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 +02001619 /* check value */
1620 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1621 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1622 return LY_EVALID;
1623 }
1624 strcpy(rev->date, temp_date);
1625 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1626
1627 /* parse content */
1628 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001629 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1630 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1631 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001632 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001633 return yin_parse_content(ctx, subelems, 3, data, LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001634}
1635
David Sedlák5e13dea2019-07-22 16:06:45 +02001636/**
1637 * @brief Parse include element.
1638 *
1639 * @param[in,out] ctx YIN parser context for logging and to store current state.
1640 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1641 * @param[in,out] data Data to read from, always moved to currently handled character.
1642 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1643 *
1644 * @return LY_ERR values.
1645 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001646static LY_ERR
1647yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1648 struct include_meta *inc_meta)
1649{
1650 struct lysp_include *inc;
1651
1652 /* allocate new include */
1653 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1654
1655 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001656 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 +02001657
1658 /* submodules share the namespace with the module names, so there must not be
1659 * a module of the same name in the context, no need for revision matching */
1660 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 +02001661 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001662 return LY_EVALID;
1663 }
1664
1665 /* parse content */
1666 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001667 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1668 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1669 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1670 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák0c2bab92019-07-22 15:33:19 +02001671 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001672 return yin_parse_content(ctx, subelems, 4, data, LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001673}
1674
David Sedlákaa854b02019-07-22 14:17:10 +02001675/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001676 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001677 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001678 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001679 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of revision-date element.
1680 * @param[in,out] data Data to read from, always moved to currently handled character.
1681 * @param[in,out] rev Array to store the parsed value in.
1682 * @param[in,out] exts Extension instances to add to.
1683 *
1684 * @return LY_ERR values.
1685 */
1686static LY_ERR
1687yin_parse_revision_date(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, char *rev,
1688 struct lysp_ext_instance **exts)
1689{
1690 const char *temp_rev;
1691 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001692 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001693 };
1694
Radek Krejcid6b76452019-09-03 17:03:03 +02001695 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 +02001696 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
1697 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
1698
1699 strcpy(rev, temp_rev);
1700 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
1701
Radek Krejcid6b76452019-09-03 17:03:03 +02001702 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001703}
1704
1705/**
1706 * @brief Parse config element.
1707 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001708 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001709 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1710 * @param[in,out] data Data to read from, always moved to currently handled character.
1711 * @param[in,out] flags Flags to add to.
1712 * @param[in,out] exts Extension instances to add to.
1713 *
1714 * @return LY_ERR values.
1715 */
1716static LY_ERR
1717yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1718 struct lysp_ext_instance **exts)
1719{
1720 const char *temp_val = NULL;
1721 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001722 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001723 };
1724
Radek Krejcid6b76452019-09-03 17:03:03 +02001725 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 +02001726 if (strcmp(temp_val, "true") == 0) {
1727 *flags |= LYS_CONFIG_W;
1728 } else if (strcmp(temp_val, "false") == 0) {
1729 *flags |= LYS_CONFIG_R;
1730 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001731 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
1732 "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001733 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1734 return LY_EVALID;
1735 }
1736 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1737
Radek Krejcid6b76452019-09-03 17:03:03 +02001738 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001739}
1740
1741/**
1742 * @brief Parse yang-version element.
1743 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001744 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001745 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yang-version element.
1746 * @param[in] data Data to read from, always moved to currently handled character.
1747 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001748 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001749 *
1750 * @return LY_ERR values.
1751 */
1752static LY_ERR
1753yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
1754 struct lysp_ext_instance **exts)
1755{
1756 const char *temp_version = NULL;
1757 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001758 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001759 };
1760
Radek Krejcid6b76452019-09-03 17:03:03 +02001761 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 +02001762 if (strcmp(temp_version, "1.0") == 0) {
1763 *version = LYS_VERSION_1_0;
1764 } else if (strcmp(temp_version, "1.1") == 0) {
1765 *version = LYS_VERSION_1_1;
1766 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001767 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
1768 "yang-version", "1.0", "1.1");
David Sedlákdfbbb442019-08-06 16:33:21 +02001769 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1770 return LY_EVALID;
1771 }
1772 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1773 ctx->mod_version = *version;
1774
Radek Krejcid6b76452019-09-03 17:03:03 +02001775 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001776}
1777
1778/**
1779 * @brief Parse import element.
1780 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001781 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001782 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1783 * @param[in,out] data Data to read from, always moved to currently handled character.
1784 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1785 *
1786 * @return LY_ERR values.
1787 */
1788static LY_ERR
1789yin_parse_import(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct import_meta *imp_meta)
1790{
1791 struct lysp_import *imp;
1792 /* allocate new element in sized array for import */
1793 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
1794
1795 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001796 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1797 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1798 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1799 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1800 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001801 };
1802
1803 /* parse import attributes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001804 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
1805 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001806 /* check prefix validity */
1807 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1808
1809 return LY_SUCCESS;
1810}
1811
1812/**
1813 * @brief Parse mandatory element.
1814 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001815 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001816 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1817 * @param[in,out] data Data to read from, always moved to currently handled character.
1818 * @param[in,out] flags Flags to add to.
1819 * @param[in,out] exts Extension instances to add to.
1820 *
1821 * @return LY_ERR values.
1822 */
1823static LY_ERR
1824yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1825 struct lysp_ext_instance **exts)
1826{
1827 const char *temp_val = NULL;
1828 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001829 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001830 };
1831
Radek Krejcid6b76452019-09-03 17:03:03 +02001832 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 +02001833 if (strcmp(temp_val, "true") == 0) {
1834 *flags |= LYS_MAND_TRUE;
1835 } else if (strcmp(temp_val, "false") == 0) {
1836 *flags |= LYS_MAND_FALSE;
1837 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001838 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1839 "mandatory", "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001840 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1841 return LY_EVALID;
1842 }
1843 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1844
Radek Krejcid6b76452019-09-03 17:03:03 +02001845 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001846}
1847
1848/**
1849 * @brief Parse status element.
1850 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001851 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001852 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1853 * @param[in,out] data Data to read from, always moved to currently handled character.
1854 * @param[in,out] flags Flags to add to.
1855 * @param[in,out] exts Extension instances to add to.
1856 *
1857 * @return LY_ERR values.
1858 */
1859static LY_ERR
1860yin_parse_status(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1861 struct lysp_ext_instance **exts)
1862{
1863 const char *value = NULL;
1864 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001865 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001866 };
1867
Radek Krejcid6b76452019-09-03 17:03:03 +02001868 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 +02001869 if (strcmp(value, "current") == 0) {
1870 *flags |= LYS_STATUS_CURR;
1871 } else if (strcmp(value, "deprecated") == 0) {
1872 *flags |= LYS_STATUS_DEPRC;
1873 } else if (strcmp(value, "obsolete") == 0) {
1874 *flags |= LYS_STATUS_OBSLT;
1875 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001876 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
1877 "status", "current", "deprecated", "obsolete");
David Sedlákdfbbb442019-08-06 16:33:21 +02001878 FREE_STRING(ctx->xml_ctx.ctx, value);
1879 return LY_EVALID;
1880 }
1881 FREE_STRING(ctx->xml_ctx.ctx, value);
1882
Radek Krejcid6b76452019-09-03 17:03:03 +02001883 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001884}
1885
1886/**
1887 * @brief Parse when element.
1888 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001889 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001890 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of when element.
1891 * @param[in,out] data Data to read from, always moved to currently handled character.
1892 * @param[out] when_p When pointer to parse to.
1893 */
1894static LY_ERR
1895yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
1896{
1897 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001898 LY_ERR ret = LY_SUCCESS;
1899
David Sedlákdfbbb442019-08-06 16:33:21 +02001900 when = calloc(1, sizeof *when);
1901 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001902 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 +02001903 LY_CHECK_ERR_RET(ret, free(when), ret);
1904
David Sedlákdfbbb442019-08-06 16:33:21 +02001905 *when_p = when;
1906 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001907 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1908 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1909 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001910 };
1911
Radek Krejcid6b76452019-09-03 17:03:03 +02001912 return yin_parse_content(ctx, subelems, 3, data, LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001913}
1914
1915/**
1916 * @brief Parse yin-elemenet element.
1917 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001918 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001919 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yin-element element.
1920 * @param[in,out] data Data to read from, always moved to currently handled position.
1921 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001922 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001923 *
1924 * @return LY_ERR values.
1925 */
1926static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001927yin_parse_yin_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdfbbb442019-08-06 16:33:21 +02001928 uint16_t *flags, struct lysp_ext_instance **exts)
1929{
1930 const char *temp_val = NULL;
1931 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001932 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001933 };
1934
Radek Krejcid6b76452019-09-03 17:03:03 +02001935 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 +02001936 if (strcmp(temp_val, "true") == 0) {
1937 *flags |= LYS_YINELEM_TRUE;
1938 } else if (strcmp(temp_val, "false") == 0) {
1939 *flags |= LYS_YINELEM_FALSE;
1940 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001941 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1942 "yin-element", "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001943 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1944 return LY_EVALID;
1945 }
1946 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1947
Radek Krejcid6b76452019-09-03 17:03:03 +02001948 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001949}
1950
1951/**
1952 * @brief Parse argument element.
1953 *
1954 * @param[in,out] xml_ctx Xml context.
1955 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of argument element.
1956 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001957 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1958 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001959 *
1960 * @return LY_ERR values.
1961 */
1962static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001963yin_parse_argument(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdfbbb442019-08-06 16:33:21 +02001964 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
1965{
1966 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001967 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1968 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001969 };
1970
Radek Krejcid6b76452019-09-03 17:03:03 +02001971 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 +02001972
Radek Krejcid6b76452019-09-03 17:03:03 +02001973 return yin_parse_content(ctx, subelems, 2, data, LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001974}
1975
1976/**
1977 * @brief Parse the extension statement.
1978 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001979 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001980 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension element.
1981 * @param[in,out] data Data to read from.
1982 * @param[in,out] extensions Extensions to add to.
1983 *
1984 * @return LY_ERR values.
1985 */
1986static LY_ERR
1987yin_parse_extension(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_ext **extensions)
1988{
1989 struct lysp_ext *ex;
1990 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001991 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 +02001992
1993 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1994 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001995 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1996 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1997 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1998 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1999 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02002000 };
2001
Radek Krejcid6b76452019-09-03 17:03:03 +02002002 return yin_parse_content(ctx, subelems, 5, data, LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002003}
2004
2005/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002006 * @brief Parse feature element.
2007 *
2008 * @param[in,out] ctx YIN parser context for logging and to store current state.
2009 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2010 * @param[in,out] data Data to read from, always moved to currently handled character.
2011 * @param[in,out] features Features to add to.
2012 *
2013 * @return LY_ERR values.
2014 */
2015static LY_ERR
2016yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2017 struct lysp_feature **features)
2018{
2019 struct lysp_feature *feat;
2020
2021 /* allocate new feature */
2022 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
2023
2024 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002025 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 +02002026
2027 /* parse content */
2028 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002029 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2030 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
2031 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2032 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2033 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák5e13dea2019-07-22 16:06:45 +02002034 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002035 return yin_parse_content(ctx, subelems, 5, data, LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02002036}
2037
2038/**
David Sedlák28794f22019-07-22 16:45:00 +02002039 * @brief Parse identity element.
2040 *
2041 * @param[in,out] ctx YIN parser context for logging and to store current state.
2042 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2043 * @param[in,out] data Data to read from, always moved to currently handled character.
2044 * @param[in,out] identities Identities to add to.
2045 *
2046 * @return LY_ERR values.
2047 */
2048static LY_ERR
2049yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2050 struct lysp_ident **identities)
2051{
2052 struct lysp_ident *ident;
2053
2054 /* allocate new identity */
2055 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
2056
2057 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002058 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 +02002059
2060 /* parse content */
2061 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002062 {LY_STMT_BASE, &ident->bases, 0},
2063 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2064 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2065 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2066 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2067 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák28794f22019-07-22 16:45:00 +02002068 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002069 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002070}
2071
2072/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002073 * @brief Parse list element.
2074 *
2075 * @param[in,out] ctx YIN parser context for logging and to store current state.
2076 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2077 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002078 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002079 *
2080 * @return LY_ERR values.
2081 */
2082static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02002083yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2084 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002085{
David Sedlákaf536aa2019-07-23 13:42:23 +02002086 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002087 LY_ERR ret = LY_SUCCESS;
2088 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02002089
David Sedlákbf8a2b72019-08-14 16:48:10 +02002090 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, list, next);
David Sedlákaf536aa2019-07-23 13:42:23 +02002091 list->nodetype = LYS_LIST;
2092 list->parent = node_meta->parent;
2093
David Sedlákaf536aa2019-07-23 13:42:23 +02002094 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002095 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 +02002096
2097 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02002098 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002099 LY_STMT_ACTION, &list->actions, 0,
2100 LY_STMT_ANYDATA, &list->child, 0,
2101 LY_STMT_ANYXML, &list->child, 0,
2102 LY_STMT_CHOICE, &list->child, 0,
2103 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2104 LY_STMT_CONTAINER, &list->child, 0,
2105 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2106 LY_STMT_GROUPING, &list->groupings, 0,
2107 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2108 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2109 LY_STMT_LEAF, &list->child, 0,
2110 LY_STMT_LEAF_LIST, &list->child, 0,
2111 LY_STMT_LIST, &list->child, 0,
2112 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2113 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2114 LY_STMT_MUST, &list->musts, 0,
2115 LY_STMT_NOTIFICATION, &list->notifs, 0,
2116 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2117 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2118 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2119 LY_STMT_TYPEDEF, &list->typedefs, 0,
2120 LY_STMT_UNIQUE, &list->uniques, 0,
2121 LY_STMT_USES, &list->child, 0,
2122 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2123 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002124 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002125 ret = yin_parse_content(ctx, subelems, 25, data, LY_STMT_LIST, NULL, &list->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002126 subelems_deallocator(25, subelems);
2127 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002128
2129 /* finalize parent pointers to the reallocated items */
2130 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
2131
2132 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02002133 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002134 return LY_EVALID;
2135 }
2136
2137 return LY_SUCCESS;
2138}
2139
2140/**
David Sedlák031b9e72019-07-23 15:19:37 +02002141 * @brief Parse notification element.
2142 *
2143 * @param[in,out] ctx YIN parser context for logging and to store current state.
2144 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2145 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02002146 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002147 *
2148 * @return LY_ERR values.
2149 */
2150static LY_ERR
2151yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002152 struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002153{
2154 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002155 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002156 LY_ERR ret = LY_SUCCESS;
2157 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002158
2159 /* allocate new notification */
David Sedlák6881b512019-08-13 12:52:00 +02002160 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002161 notif->nodetype = LYS_NOTIF;
2162 notif->parent = notif_meta->parent;
2163
2164 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002165 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 +02002166
2167 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002168 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002169 LY_STMT_ANYDATA, &notif->data, 0,
2170 LY_STMT_ANYXML, &notif->data, 0,
2171 LY_STMT_CHOICE, &notif->data, 0,
2172 LY_STMT_CONTAINER, &notif->data, 0,
2173 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2174 LY_STMT_GROUPING, &notif->groupings, 0,
2175 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2176 LY_STMT_LEAF, &notif->data, 0,
2177 LY_STMT_LEAF_LIST, &notif->data, 0,
2178 LY_STMT_LIST, &notif->data, 0,
2179 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2180 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2181 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2182 LY_STMT_TYPEDEF, &notif->typedefs, 0,
2183 LY_STMT_USES, &notif->data, 0,
2184 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002185 ));
2186
Radek Krejcid6b76452019-09-03 17:03:03 +02002187 ret = yin_parse_content(ctx, subelems, 16, data, LY_STMT_NOTIFICATION, NULL, &notif->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002188 subelems_deallocator(16, subelems);
2189 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002190
2191 /* finalize parent pointers to the reallocated items */
2192 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2193
2194 return LY_SUCCESS;
2195}
2196
2197/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002198 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002199 *
2200 * @param[in,out] ctx YIN parser context for logging and to store current state.
2201 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2202 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002203 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002204 *
2205 * @return LY_ERR values.
2206 */
2207static LY_ERR
2208yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002209 struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002210{
2211 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002212 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002213 LY_ERR ret = LY_SUCCESS;
2214 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002215
2216 /* create new grouping */
David Sedlák6881b512019-08-13 12:52:00 +02002217 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002218 grp->nodetype = LYS_GROUPING;
2219 grp->parent = gr_meta->parent;
2220
2221 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002222 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 +02002223
2224 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002225 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002226 LY_STMT_ACTION, &grp->actions, 0,
2227 LY_STMT_ANYDATA, &grp->data, 0,
2228 LY_STMT_ANYXML, &grp->data, 0,
2229 LY_STMT_CHOICE, &grp->data, 0,
2230 LY_STMT_CONTAINER, &grp->data, 0,
2231 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2232 LY_STMT_GROUPING, &grp->groupings, 0,
2233 LY_STMT_LEAF, &grp->data, 0,
2234 LY_STMT_LEAF_LIST, &grp->data, 0,
2235 LY_STMT_LIST, &grp->data, 0,
2236 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2237 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2238 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2239 LY_STMT_TYPEDEF, &grp->typedefs, 0,
2240 LY_STMT_USES, &grp->data, 0,
2241 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002242 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002243 ret = yin_parse_content(ctx, subelems, 16, data, LY_STMT_GROUPING, NULL, &grp->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002244 subelems_deallocator(16, subelems);
2245 LY_CHECK_RET(ret);
2246
David Sedláke3ce9ef2019-07-23 16:34:30 +02002247 /* finalize parent pointers to the reallocated items */
2248 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2249
2250 return LY_SUCCESS;
2251}
2252
2253/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002254 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002255 *
2256 * @param[in,out] ctx YIN parser context for logging and to store current state.
2257 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2258 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002259 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002260 *
2261 * @return LY_ERR values.
2262 */
2263static LY_ERR
2264yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2265 struct tree_node_meta *node_meta)
2266{
David Sedlákf111bcb2019-07-23 17:15:51 +02002267 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002268 LY_ERR ret = LY_SUCCESS;
2269 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002270
2271 /* create new container */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002272 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, cont, next);
David Sedlákf111bcb2019-07-23 17:15:51 +02002273 cont->nodetype = LYS_CONTAINER;
2274 cont->parent = node_meta->parent;
2275
David Sedlákf111bcb2019-07-23 17:15:51 +02002276 /* parse aegument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002277 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 +02002278
2279 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002280 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002281 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2282 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2283 LY_STMT_ANYXML, &cont->child, 0,
2284 LY_STMT_CHOICE, &cont->child, 0,
2285 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2286 LY_STMT_CONTAINER, &cont->child, 0,
2287 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2288 LY_STMT_GROUPING, &cont->groupings, 0,
2289 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2290 LY_STMT_LEAF, &cont->child, 0,
2291 LY_STMT_LEAF_LIST, &cont->child, 0,
2292 LY_STMT_LIST, &cont->child, 0,
2293 LY_STMT_MUST, &cont->musts, 0,
2294 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2295 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2296 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2297 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2298 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2299 LY_STMT_USES, &cont->child, 0,
2300 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2301 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002302 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002303 ret = yin_parse_content(ctx, subelems, 21, data, LY_STMT_CONTAINER, NULL, &cont->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002304 subelems_deallocator(21, subelems);
2305 LY_CHECK_RET(ret);
2306
David Sedlákf111bcb2019-07-23 17:15:51 +02002307 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2308
2309 return LY_SUCCESS;
2310}
2311
2312/**
David Sedlák5379d392019-07-24 10:42:03 +02002313 * @brief Parse case element.
2314 *
2315 * @param[in,out] ctx YIN parser context for logging and to store current state.
2316 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2317 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002318 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002319 *
2320 * @return LY_ERR values.
2321 */
2322static LY_ERR
2323yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2324 struct tree_node_meta *node_meta)
2325{
David Sedlák5379d392019-07-24 10:42:03 +02002326 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002327 LY_ERR ret = LY_SUCCESS;
2328 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002329
2330 /* create new case */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002331 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, cas, next);
David Sedlák5379d392019-07-24 10:42:03 +02002332 cas->nodetype = LYS_CASE;
2333 cas->parent = node_meta->parent;
2334
David Sedlák5379d392019-07-24 10:42:03 +02002335 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002336 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 +02002337
2338 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002339 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002340 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2341 LY_STMT_ANYXML, &cas->child, 0,
2342 LY_STMT_CHOICE, &cas->child, 0,
2343 LY_STMT_CONTAINER, &cas->child, 0,
2344 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2345 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2346 LY_STMT_LEAF, &cas->child, 0,
2347 LY_STMT_LEAF_LIST, &cas->child, 0,
2348 LY_STMT_LIST, &cas->child, 0,
2349 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2350 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2351 LY_STMT_USES, &cas->child, 0,
2352 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2353 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002354 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002355 ret = yin_parse_content(ctx, subelems, 14, data, LY_STMT_CASE, NULL, &cas->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002356 subelems_deallocator(14, subelems);
2357
2358 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002359}
2360
2361/**
David Sedlák05404f62019-07-24 14:11:53 +02002362 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002363 *
2364 * @param[in,out] ctx YIN parser context for logging and to store current state.
2365 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2366 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002367 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002368 *
2369 * @return LY_ERR values.
2370 */
2371LY_ERR
2372yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2373 struct tree_node_meta *node_meta)
2374{
David Sedlák81497a32019-08-13 16:56:26 +02002375 LY_ERR ret = LY_SUCCESS;
2376 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002377 struct lysp_node_choice *choice;
2378
2379 /* create new choice */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002380 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, choice, next);
David Sedlák8d552d62019-08-06 15:29:05 +02002381
David Sedlákb7abcfa2019-07-24 12:33:35 +02002382 choice->nodetype = LYS_CHOICE;
2383 choice->parent = node_meta->parent;
2384
David Sedlákb7abcfa2019-07-24 12:33:35 +02002385 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002386 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 +02002387
2388 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002389 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002390 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2391 LY_STMT_ANYXML, &choice->child, 0,
2392 LY_STMT_CASE, &choice->child, 0,
2393 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2394 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2395 LY_STMT_CONTAINER, &choice->child, 0,
2396 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2397 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2398 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2399 LY_STMT_LEAF, &choice->child, 0,
2400 LY_STMT_LEAF_LIST, &choice->child, 0,
2401 LY_STMT_LIST, &choice->child, 0,
2402 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2403 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2404 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2405 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2406 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002407 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002408 ret = yin_parse_content(ctx, subelems, 17, data, LY_STMT_CHOICE, NULL, &choice->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002409 subelems_deallocator(17, subelems);
2410 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002411}
2412
2413/**
David Sedlák05404f62019-07-24 14:11:53 +02002414 * @brief Parse input or output element.
2415 *
2416 * @param[in,out] ctx YIN parser context for logging and to store current state.
2417 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2418 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002419 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002420 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2421 *
2422 * @return LY_ERR values.
2423 */
2424static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02002425yin_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 +02002426 struct inout_meta *inout_meta)
2427{
David Sedlák81497a32019-08-13 16:56:26 +02002428 LY_ERR ret = LY_SUCCESS;
2429 struct yin_subelement *subelems = NULL;
2430
David Sedlák05404f62019-07-24 14:11:53 +02002431 /* initiate structure */
Radek Krejcid6b76452019-09-03 17:03:03 +02002432 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002433 inout_meta->inout_p->parent = inout_meta->parent;
2434
2435 /* check attributes */
2436 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
2437
2438 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002439 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002440 LY_STMT_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2441 LY_STMT_ANYXML, &inout_meta->inout_p->data, 0,
2442 LY_STMT_CHOICE, &inout_meta->inout_p->data, 0,
2443 LY_STMT_CONTAINER, &inout_meta->inout_p->data, 0,
2444 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2445 LY_STMT_LEAF, &inout_meta->inout_p->data, 0,
2446 LY_STMT_LEAF_LIST, &inout_meta->inout_p->data, 0,
2447 LY_STMT_LIST, &inout_meta->inout_p->data, 0,
2448 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2449 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2450 LY_STMT_USES, &inout_meta->inout_p->data, 0,
2451 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002452 ));
2453 ret = yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts);
2454 subelems_deallocator(12, subelems);
2455 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002456
2457 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002458 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 +02002459
2460 return LY_SUCCESS;
2461}
2462
David Sedlák992fb7c2019-07-24 16:51:01 +02002463/**
2464 * @brief Parse action element.
2465 *
2466 * @param[in,out] ctx YIN parser context for logging and to store current state.
2467 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2468 * @param[in,out] data Data to read from, always moved to currently handled character.
2469 * @param[in] act_meta Meta information about parent node and actions to add to.
2470 *
2471 * @return LY_ERR values.
2472 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002473static LY_ERR
2474yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002475 struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002476{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002477 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002478 LY_ERR ret = LY_SUCCESS;
2479 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002480
2481 /* create new action */
David Sedlák6881b512019-08-13 12:52:00 +02002482 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *acts, act, LY_EMEM);
David Sedlák85d0eca2019-07-24 15:15:21 +02002483 act->nodetype = LYS_ACTION;
2484 act->parent = act_meta->parent;
2485
2486 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002487 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 +02002488
2489 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002490 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002491 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2492 LY_STMT_GROUPING, &act->groupings, 0,
2493 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2494 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2495 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2496 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2497 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2498 LY_STMT_TYPEDEF, &act->typedefs, 0,
2499 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002500 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002501 ret = (yin_parse_content(ctx, subelems, 9, data, LY_STMT_ACTION, NULL, &act->exts));
David Sedlák81497a32019-08-13 16:56:26 +02002502 subelems_deallocator(9, subelems);
2503 LY_CHECK_RET(ret);
2504
David Sedlák85d0eca2019-07-24 15:15:21 +02002505 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2506
2507 return LY_SUCCESS;
2508}
2509
David Sedlák05404f62019-07-24 14:11:53 +02002510/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002511 * @brief Parse augment element.
2512 *
2513 * @param[in,out] ctx YIN parser context for logging and to store current state.
2514 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2515 * @param[in,out] data Data to read from, always moved to currently handled character.
2516 * @param[in] aug_meta Meta information about parent node and augments to add to.
2517 *
2518 * @return LY_ERR values.
2519 */
2520static LY_ERR
2521yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002522 struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002523{
2524 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002525 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002526 LY_ERR ret = LY_SUCCESS;
2527 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002528
2529 /* create new augment */
David Sedlák6881b512019-08-13 12:52:00 +02002530 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002531 aug->nodetype = LYS_AUGMENT;
2532 aug->parent = aug_meta->parent;
2533
2534 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002535 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 +02002536 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2537
2538 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002539 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002540 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2541 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2542 LY_STMT_ANYXML, &aug->child, 0,
2543 LY_STMT_CASE, &aug->child, 0,
2544 LY_STMT_CHOICE, &aug->child, 0,
2545 LY_STMT_CONTAINER, &aug->child, 0,
2546 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2547 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
2548 LY_STMT_LEAF, &aug->child, 0,
2549 LY_STMT_LEAF_LIST, &aug->child, 0,
2550 LY_STMT_LIST, &aug->child, 0,
2551 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2552 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2553 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2554 LY_STMT_USES, &aug->child, 0,
2555 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2556 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002557 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002558 ret = yin_parse_content(ctx, subelems, 17, data, LY_STMT_AUGMENT, NULL, &aug->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002559 subelems_deallocator(17, subelems);
2560 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002561
2562 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2563
2564 return LY_SUCCESS;
2565}
2566
David Sedlák8b754462019-07-25 16:22:13 +02002567/**
2568 * @brief Parse deviate element.
2569 *
2570 * @param[in,out] ctx YIN parser context for logging and to store current state.
2571 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2572 * @param[in,out] data Data to read from, always moved to currently handled character.
2573 * @param[in] deviates Deviates to add to.
2574 *
2575 * @return LY_ERR values.
2576 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002577static LY_ERR
2578yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2579 struct lysp_deviate **deviates)
2580{
2581 LY_ERR ret = LY_SUCCESS;
2582 uint8_t dev_mod;
2583 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002584 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002585 struct lysp_deviate_add *d_add = NULL;
2586 struct lysp_deviate_rpl *d_rpl = NULL;
2587 struct lysp_deviate_del *d_del = NULL;
2588
2589 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002590 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 +02002591
2592 if (strcmp(temp_val, "not-supported") == 0) {
2593 dev_mod = LYS_DEV_NOT_SUPPORTED;
2594 } else if (strcmp(temp_val, "add") == 0) {
2595 dev_mod = LYS_DEV_ADD;
2596 } else if (strcmp(temp_val, "replace") == 0) {
2597 dev_mod = LYS_DEV_REPLACE;
2598 } else if (strcmp(temp_val, "delete") == 0) {
2599 dev_mod = LYS_DEV_DELETE;
2600 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002601 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
2602 "not-supported", "add", "replace", "delete");
David Sedlák4ffcec82019-07-25 15:10:21 +02002603 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2604 return LY_EVALID;
2605 }
2606 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2607
2608 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2609 d = calloc(1, sizeof *d);
2610 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2611 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002612 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák4ffcec82019-07-25 15:10:21 +02002613 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002614 ret = yin_parse_content(ctx, subelems, 1, data, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002615
2616 } else if (dev_mod == LYS_DEV_ADD) {
2617 d_add = calloc(1, sizeof *d_add);
2618 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2619 d = (struct lysp_deviate *)d_add;
2620 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2621 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2622 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002623 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2624 {LY_STMT_DEFAULT, &d_add->dflts, 0},
2625 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2626 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2627 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2628 {LY_STMT_MUST, &d_add->musts, 0},
2629 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2630 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2631 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002632 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002633 ret = yin_parse_content(ctx, subelems, 9, data, LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002634
2635 } else if (dev_mod == LYS_DEV_REPLACE) {
2636 d_rpl = calloc(1, sizeof *d_rpl);
2637 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2638 d = (struct lysp_deviate *)d_rpl;
2639 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2640 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2641 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002642 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2643 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2644 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2645 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2646 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2647 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2648 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2649 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002650 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002651 ret = yin_parse_content(ctx, subelems, 8, data, LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002652
2653 } else {
2654 d_del = calloc(1, sizeof *d_del);
2655 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2656 d = (struct lysp_deviate *)d_del;
2657 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002658 {LY_STMT_DEFAULT, &d_del->dflts, 0},
2659 {LY_STMT_MUST, &d_del->musts, 0},
2660 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2661 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2662 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002663 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002664 ret = yin_parse_content(ctx, subelems, 5, data, LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002665 }
2666 LY_CHECK_GOTO(ret, cleanup);
2667
2668 d->mod = dev_mod;
2669 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002670 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002671
2672 return ret;
2673
2674cleanup:
2675 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002676 return ret;
2677}
2678
David Sedlák992fb7c2019-07-24 16:51:01 +02002679/**
David Sedlák8b754462019-07-25 16:22:13 +02002680 * @brief Parse deviation element.
2681 *
2682 * @param[in,out] ctx YIN parser context for logging and to store current state.
2683 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2684 * @param[in,out] data Data to read from, always moved to currently handled character.
2685 * @param[in] deviations Deviations to add to.
2686 *
2687 * @return LY_ERR values.
2688 */
2689static LY_ERR
2690yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2691 struct lysp_deviation **deviations)
2692{
2693 struct lysp_deviation *dev;
2694
2695 /* create new deviation */
2696 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2697
2698 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002699 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 +02002700 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2701 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002702 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2703 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2704 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2705 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8b754462019-07-25 16:22:13 +02002706 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002707 return yin_parse_content(ctx, subelems, 4, data, LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002708}
2709
2710/**
David Sedlákb4e44562019-07-04 15:42:12 +02002711 * @brief Map keyword type to substatement info.
2712 *
2713 * @param[in] kw Keyword type.
2714 *
2715 * @return correct LYEXT_SUBSTMT information.
2716 */
2717static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002718kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002719{
2720 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002721 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002722 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002723 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002724 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002725 case LY_STMT_BELONGS_TO:
David Sedlákb4e44562019-07-04 15:42:12 +02002726 return LYEXT_SUBSTMT_BELONGSTO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002727 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002728 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002729 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002730 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002731 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002732 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002733 case LY_STMT_ERROR_APP_TAG:
David Sedlákb4e44562019-07-04 15:42:12 +02002734 return LYEXT_SUBSTMT_ERRTAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002735 case LY_STMT_ERROR_MESSAGE:
David Sedlákb4e44562019-07-04 15:42:12 +02002736 return LYEXT_SUBSTMT_ERRMSG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002737 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002738 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002739 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002740 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002741 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002742 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002743 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002744 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002745 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002746 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002747 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002748 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002749 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002750 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002751 case LY_STMT_REVISION_DATE:
David Sedlákb4e44562019-07-04 15:42:12 +02002752 return LYEXT_SUBSTMT_REVISIONDATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002753 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002754 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002755 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002756 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002757 case LY_STMT_YANG_VERSION:
David Sedlákb4e44562019-07-04 15:42:12 +02002758 return LYEXT_SUBSTMT_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002759 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002760 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002761 case LY_STMT_REQUIRE_INSTANCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002762 return LYEXT_SUBSTMT_REQINSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002763 case LY_STMT_YIN_ELEMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002764 return LYEXT_SUBSTMT_YINELEM;
Radek Krejcid6b76452019-09-03 17:03:03 +02002765 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002766 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002767 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002768 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002769 case LY_STMT_ORDERED_BY:
David Sedlákb4e44562019-07-04 15:42:12 +02002770 return LYEXT_SUBSTMT_ORDEREDBY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002771 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002772 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002773 case LY_STMT_FRACTION_DIGITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002774 return LYEXT_SUBSTMT_FRACDIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002775 case LY_STMT_MAX_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002776 return LYEXT_SUBSTMT_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002777 case LY_STMT_MIN_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002778 return LYEXT_SUBSTMT_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02002779 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002780 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002781 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002782 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002783 case LY_STMT_IF_FEATURE:
David Sedlákb4e44562019-07-04 15:42:12 +02002784 return LYEXT_SUBSTMT_IFFEATURE;
2785 default:
2786 return LYEXT_SUBSTMT_SELF;
2787 }
2788}
2789
David Sedlákc5b20842019-08-13 10:18:31 +02002790/**
2791 * @brief map keyword to keyword-group.
2792 *
2793 * @param[in] ctx YIN parser context used for logging.
2794 * @param[in] kw Keyword that is child of module or submodule.
2795 * @param[out] group Group of keyword.
2796 *
2797 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2798 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002799static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02002800kw2kw_group(struct yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002801{
2802 switch (kw) {
2803 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02002804 case LY_STMT_NONE:
2805 case LY_STMT_NAMESPACE:
2806 case LY_STMT_PREFIX:
2807 case LY_STMT_BELONGS_TO:
2808 case LY_STMT_YANG_VERSION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002809 *group = Y_MOD_MODULE_HEADER;
2810 break;
2811 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02002812 case LY_STMT_INCLUDE:
2813 case LY_STMT_IMPORT:
David Sedláke6cd89e2019-08-07 12:46:02 +02002814 *group = Y_MOD_LINKAGE;
2815 break;
2816 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02002817 case LY_STMT_ORGANIZATION:
2818 case LY_STMT_CONTACT:
2819 case LY_STMT_DESCRIPTION:
2820 case LY_STMT_REFERENCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002821 *group = Y_MOD_META;
2822 break;
2823 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02002824 case LY_STMT_REVISION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002825 *group = Y_MOD_REVISION;
2826 break;
2827 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02002828 case LY_STMT_ANYDATA:
2829 case LY_STMT_ANYXML:
2830 case LY_STMT_AUGMENT:
2831 case LY_STMT_CHOICE:
2832 case LY_STMT_CONTAINER:
2833 case LY_STMT_DEVIATION:
2834 case LY_STMT_EXTENSION:
2835 case LY_STMT_FEATURE:
2836 case LY_STMT_GROUPING:
2837 case LY_STMT_IDENTITY:
2838 case LY_STMT_LEAF:
2839 case LY_STMT_LEAF_LIST:
2840 case LY_STMT_LIST:
2841 case LY_STMT_NOTIFICATION:
2842 case LY_STMT_RPC:
2843 case LY_STMT_TYPEDEF:
2844 case LY_STMT_USES:
2845 case LY_STMT_EXTENSION_INSTANCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002846 *group = Y_MOD_BODY;
2847 break;
2848 default:
2849 LOGINT(ctx->xml_ctx.ctx);
2850 return LY_EINT;
2851 }
2852
2853 return LY_SUCCESS;
2854}
2855
David Sedlákc5b20842019-08-13 10:18:31 +02002856/**
2857 * @brief Check if relative order of two keywords is valid.
2858 *
2859 * @param[in] ctx YIN parser context used for logging.
2860 * @param[in] kw Current keyword.
2861 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002862 * @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 +02002863 * because relative order is required only in module and submodule sub-elements, used for logging.
2864 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002865 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002866 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002867static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02002868yin_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 +02002869{
Radek Krejcid6b76452019-09-03 17:03:03 +02002870 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002871 enum yang_module_stmt gr, next_gr;
2872
2873 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2874 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2875
2876 if (gr > next_gr) {
2877 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2878 return LY_EVALID;
2879 }
2880
2881 return LY_SUCCESS;
2882}
2883
David Sedlákd6e56892019-07-01 15:40:24 +02002884LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002885yin_parse_content(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info, signed char subelem_info_size,
Radek Krejcid6b76452019-09-03 17:03:03 +02002886 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 +02002887{
2888 LY_ERR ret = LY_SUCCESS;
David Sedlák8e7bda82019-07-16 17:57:50 +02002889 char *out = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +02002890 const char *prefix, *name;
2891 size_t out_len = 0, prefix_len, name_len;
David Sedlák8e7bda82019-07-16 17:57:50 +02002892 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002893 struct yin_arg_record *attrs = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +02002894 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002895 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002896
David Sedlákb0faad82019-07-04 14:28:59 +02002897 assert(is_ordered(subelem_info, subelem_info_size));
David Sedlákd6e56892019-07-01 15:40:24 +02002898
David Sedlákda8ffa32019-07-08 14:17:10 +02002899 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2900 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002901 /* current element has subelements as content */
2902 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002903 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákc5b20842019-08-13 10:18:31 +02002904 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákd6e56892019-07-01 15:40:24 +02002905 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +02002906 if (!name) {
David Sedlákd6e56892019-07-01 15:40:24 +02002907 /* end of current element reached */
2908 break;
2909 }
David Sedlák1af868e2019-07-17 17:03:14 +02002910 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002911 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6cd89e2019-08-07 12:46:02 +02002912 last_kw = kw;
David Sedlákc5b20842019-08-13 10:18:31 +02002913 kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002914
2915 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002916 subelem = get_record(kw, subelem_info_size, subelem_info);
2917 if (!subelem) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002918 if (current_element == LY_STMT_DEVIATE && isdevsub(kw)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002919 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2920 } else {
David Sedlákc5b20842019-08-13 10:18:31 +02002921 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 +02002922 }
David Sedlákd6e56892019-07-01 15:40:24 +02002923 ret = LY_EVALID;
2924 goto cleanup;
2925 }
2926
David Sedlák6542aed2019-08-14 10:47:43 +02002927 /* relative order is required only in module and submodule sub-elements */
Radek Krejcid6b76452019-09-03 17:03:03 +02002928 if (current_element == LY_STMT_MODULE || current_element == LY_STMT_SUBMODULE) {
David Sedláke6cd89e2019-08-07 12:46:02 +02002929 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2930 LY_CHECK_GOTO(ret, cleanup);
2931 }
David Sedlák5f8191e2019-07-08 16:35:52 +02002932
David Sedlák4ffcec82019-07-25 15:10:21 +02002933 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002934 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002935 /* subelement uniquenes */
David Sedlák1538a842019-08-08 15:38:51 +02002936 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 +02002937 return LY_EVALID;
2938 }
David Sedlák1af868e2019-07-17 17:03:14 +02002939 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002940 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002941 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002942 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002943 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002944 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002945 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002946 if (ctx->mod_version < 2) {
David Sedlák1538a842019-08-08 15:38:51 +02002947 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 +02002948 ret = LY_EVALID;
2949 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002950 }
2951 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002952 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002953 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002954
David Sedlákd6e56892019-07-01 15:40:24 +02002955 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002956 /* call responsible function */
Radek Krejcid6b76452019-09-03 17:03:03 +02002957 case LY_STMT_EXTENSION_INSTANCE:
David Sedláka82ecff2019-08-16 10:51:48 +02002958 ret = yin_parse_extension_instance(ctx, attrs, data, name2fname(name, prefix_len),
2959 len2flen(name_len, prefix_len),
David Sedlák1af868e2019-07-17 17:03:14 +02002960 kw2lyext_substmt(current_element),
2961 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002962 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002963 case LY_STMT_ACTION:
2964 case LY_STMT_RPC:
David Sedlák6881b512019-08-13 12:52:00 +02002965 ret = yin_parse_action(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002966 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002967 case LY_STMT_ANYDATA:
2968 case LY_STMT_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002969 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002970 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002971 case LY_STMT_ARGUMENT:
David Sedlákdf2691f2019-08-15 13:32:27 +02002972 ret = yin_parse_argument(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002973 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002974 case LY_STMT_AUGMENT:
David Sedlák6881b512019-08-13 12:52:00 +02002975 ret = yin_parse_augment(ctx, attrs, data, (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_BASE:
David Sedlák6542aed2019-08-14 10:47:43 +02002978 ret = yin_parse_base(ctx, attrs, data, current_element, subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002979 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002980 case LY_STMT_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002981 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002982 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002983 case LY_STMT_BIT:
David Sedlák43801c92019-08-05 15:58:54 +02002984 ret = yin_parse_bit(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002985 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002986 case LY_STMT_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002987 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002988 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002989 case LY_STMT_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002990 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002991 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002992 case LY_STMT_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02002993 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002994 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002995 case LY_STMT_CONTACT:
2996 case LY_STMT_DESCRIPTION:
2997 case LY_STMT_ORGANIZATION:
2998 case LY_STMT_REFERENCE:
David Sedlákdf2691f2019-08-15 13:32:27 +02002999 ret = yin_parse_meta(ctx, attrs, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003000 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003001 case LY_STMT_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02003002 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003003 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003004 case LY_STMT_DEFAULT:
3005 case LY_STMT_ERROR_APP_TAG:
3006 case LY_STMT_KEY:
3007 case LY_STMT_PRESENCE:
David Sedlák6542aed2019-08-14 10:47:43 +02003008 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 +02003009 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003010 case LY_STMT_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02003011 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003012 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003013 case LY_STMT_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02003014 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003015 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003016 case LY_STMT_ENUM:
David Sedlák43801c92019-08-05 15:58:54 +02003017 ret = yin_parse_enum(ctx, attrs, data, (struct lysp_type *)subelem->dest);
3018 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003019 case LY_STMT_ERROR_MESSAGE:
David Sedlákdf2691f2019-08-15 13:32:27 +02003020 ret = yin_parse_err_msg(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003021 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003022 case LY_STMT_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003023 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003024 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003025 case LY_STMT_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02003026 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003027 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003028 case LY_STMT_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02003029 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003030 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003031 case LY_STMT_GROUPING:
David Sedlák6881b512019-08-13 12:52:00 +02003032 ret = yin_parse_grouping(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003033 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003034 case LY_STMT_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02003035 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003036 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003037 case LY_STMT_IF_FEATURE:
3038 case LY_STMT_UNITS:
David Sedlák6542aed2019-08-14 10:47:43 +02003039 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 +02003040 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003041 case LY_STMT_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02003042 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003043 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003044 case LY_STMT_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02003045 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003046 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003047 case LY_STMT_INPUT:
3048 case LY_STMT_OUTPUT:
David Sedlák05404f62019-07-24 14:11:53 +02003049 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003050 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003051 case LY_STMT_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02003052 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003053 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003054 case LY_STMT_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02003055 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003056 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003057 case LY_STMT_LENGTH:
David Sedlák6542aed2019-08-14 10:47:43 +02003058 ret = yin_parse_length(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003059 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003060 case LY_STMT_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02003061 ret = yin_parse_list(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_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02003064 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003065 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003066 case LY_STMT_MAX_ELEMENTS:
3067 case LY_STMT_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02003068 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003069 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003070 case LY_STMT_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02003071 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003072 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003073 case LY_STMT_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02003074 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003075 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003076 case LY_STMT_NAMESPACE:
David Sedlák6542aed2019-08-14 10:47:43 +02003077 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 +02003078 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003079 case LY_STMT_NOTIFICATION:
David Sedlák6881b512019-08-13 12:52:00 +02003080 ret = yin_parse_notification(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003081 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003082 case LY_STMT_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02003083 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003084 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003085 case LY_STMT_PATH:
David Sedlák6542aed2019-08-14 10:47:43 +02003086 ret = yin_parse_path(ctx, attrs, data, kw, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003087 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003088 case LY_STMT_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02003089 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003090 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003091 case LY_STMT_VALUE:
3092 case LY_STMT_POSITION:
David Sedlákdf2691f2019-08-15 13:32:27 +02003093 ret = yin_parse_value_pos(ctx, attrs, data, kw, (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003094 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003095 case LY_STMT_PREFIX:
David Sedlák6542aed2019-08-14 10:47:43 +02003096 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 +02003097 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003098 case LY_STMT_RANGE:
David Sedlák6542aed2019-08-14 10:47:43 +02003099 ret = yin_parse_range(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003100 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003101 case LY_STMT_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02003102 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003103 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003104 case LY_STMT_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02003105 ret = yin_pasrse_reqinstance(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_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02003108 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003109 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003110 case LY_STMT_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02003111 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003112 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003113 case LY_STMT_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02003114 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003115 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003116 case LY_STMT_TYPE:
David Sedlák6542aed2019-08-14 10:47:43 +02003117 ret = yin_parse_type(ctx, attrs, data, current_element, subelem);
David Sedlákd6e56892019-07-01 15:40:24 +02003118 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003119 case LY_STMT_TYPEDEF:
David Sedlák6881b512019-08-13 12:52:00 +02003120 ret = yin_parse_typedef(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003121 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003122 case LY_STMT_UNIQUE:
David Sedlák6542aed2019-08-14 10:47:43 +02003123 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 +02003124 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003125 case LY_STMT_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02003126 ret = yin_parse_uses(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_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02003129 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003130 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003131 case LY_STMT_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003132 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003133 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003134 case LY_STMT_YIN_ELEMENT:
David Sedlákdf2691f2019-08-15 13:32:27 +02003135 ret = yin_parse_yin_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02003136 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003137 case LY_STMT_ARG_TEXT:
3138 case LY_STMT_ARG_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02003139 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02003140 break;
3141 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02003142 LOGINT(ctx->xml_ctx.ctx);
David Sedlákbf8a2b72019-08-14 16:48:10 +02003143 ret = LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02003144 }
David Sedlák3ffbc522019-07-02 17:49:28 +02003145 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02003146 FREE_ARRAY(ctx, attrs, free_arg_rec);
3147 attrs = NULL;
3148 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02003149 }
3150 } else {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003151 LY_CHECK_RET(ret);
David Sedlákd6e56892019-07-01 15:40:24 +02003152 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02003153 /* save text content, if text_content isn't set, it's just ignored */
David Sedlákc5b20842019-08-13 10:18:31 +02003154 /* no resources are allocated in this branch, no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02003155 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02003156 if (text_content) {
David Sedlák169cc522019-08-15 13:23:45 +02003157 INSERT_STRING(ctx->xml_ctx.ctx, *text_content, dynamic, out, out_len);
3158 LY_CHECK_RET(!*text_content, LY_EMEM);
David Sedlák3ffbc522019-07-02 17:49:28 +02003159 }
David Sedlákd6e56892019-07-01 15:40:24 +02003160 /* load closing element */
David Sedlákc5b20842019-08-13 10:18:31 +02003161 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákd6e56892019-07-01 15:40:24 +02003162 }
3163 }
David Sedlák8b754462019-07-25 16:22:13 +02003164 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3165 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003166
3167cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02003168 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02003169 return ret;
3170}
3171
David Sedlák619db942019-07-03 14:47:30 +02003172LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02003173yin_parse_extension_instance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, const char *ext_name,
David Sedlák619db942019-07-03 14:47:30 +02003174 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003175{
3176 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003177 char *out;
3178 const char *name, *prefix;
3179 size_t out_len, prefix_len, name_len;
3180 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003181 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003182 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
3183 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003184
David Sedlákda8ffa32019-07-08 14:17:10 +02003185 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003186
3187 e->yin = 0;
3188 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02003189 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02003190 e->insubstmt = subelem;
3191 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003192 e->yin |= LYS_YIN;
3193
David Sedlákb1a78352019-06-28 16:16:29 +02003194 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02003195 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02003196 if (!iter->prefix) {
3197 new_subelem = calloc(1, sizeof(*new_subelem));
3198 if (!e->child) {
3199 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003200 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003201 last_subelem->next = new_subelem;
3202 }
3203 last_subelem = new_subelem;
3204
3205 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003206 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
David Sedlák169cc522019-08-15 13:23:45 +02003207 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3208
3209 INSERT_STRING(ctx->xml_ctx.ctx, last_subelem->arg, iter->dynamic_content, iter->content, iter->content_len);
3210 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003211 }
3212 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003213
David Sedlákf250ecf2019-07-01 11:02:05 +02003214 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003215 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3216 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003217 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003218 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3219 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02003220 if (!name) {
3221 /* end of extension instance reached */
3222 break;
3223 }
David Sedláka82ecff2019-08-16 10:51:48 +02003224 LY_CHECK_RET(yin_parse_element_generic(ctx, name2fname(name, prefix_len),
3225 len2flen(name_len, prefix_len), data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02003226 if (!e->child) {
3227 e->child = new_subelem;
3228 } else {
3229 last_subelem->next = new_subelem;
3230 }
3231 last_subelem = new_subelem;
3232 }
David Sedlák555c7202019-07-04 12:14:12 +02003233 } else {
David Sedlák169cc522019-08-15 13:23:45 +02003234 if (out_len != 0) {
3235 /* save text content */
3236 LY_CHECK_RET(ret);
3237
3238 INSERT_STRING(ctx->xml_ctx.ctx, e->argument, dynamic, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02003239 LY_CHECK_RET(!e->argument, LY_EMEM);
David Sedlák169cc522019-08-15 13:23:45 +02003240
3241 /* load closing element */
3242 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
3243 LY_CHECK_RET(name, LY_EINT);
David Sedlák555c7202019-07-04 12:14:12 +02003244 }
David Sedlákb1a78352019-06-28 16:16:29 +02003245 }
David Sedlákb1a78352019-06-28 16:16:29 +02003246 }
3247
3248 return LY_SUCCESS;
3249}
3250
3251LY_ERR
David Sedlák4ffcec82019-07-25 15:10:21 +02003252yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char **data,
3253 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02003254{
3255 LY_ERR ret = LY_SUCCESS;
3256 const char *temp_prefix, *temp_name;
3257 char *out = NULL;
David Sedlák4ffcec82019-07-25 15:10:21 +02003258 size_t out_len, temp_name_len, temp_prefix_len, prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02003259 int dynamic;
David Sedlákb1a78352019-06-28 16:16:29 +02003260 struct lysp_stmt *last = NULL, *new = NULL;
3261
3262 /* allocate new structure for element */
3263 *element = calloc(1, sizeof(**element));
David Sedlákc005d892019-08-16 09:27:01 +02003264 LY_CHECK_ERR_RET(!(*element), LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákda8ffa32019-07-08 14:17:10 +02003265 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, name, name_len);
David Sedlákc005d892019-08-16 09:27:01 +02003266 LY_CHECK_RET(!(*element)->stmt, LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003267
3268 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +02003269 /* load attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +02003270 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákb1a78352019-06-28 16:16:29 +02003271 /* add new element to linked-list */
3272 new = calloc(1, sizeof(*last));
David Sedlákc005d892019-08-16 09:27:01 +02003273 LY_CHECK_ERR_RET(!new, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003274 if (!(*element)->child) {
3275 /* save first */
3276 (*element)->child = new;
3277 } else {
3278 last->next = new;
3279 }
3280 last = new;
3281
3282 last->flags |= LYS_YIN_ATTR;
David Sedlákc005d892019-08-16 09:27:01 +02003283 LY_CHECK_RET(lyxml_get_attribute(&ctx->xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len));
David Sedlákda8ffa32019-07-08 14:17:10 +02003284 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
David Sedlákc005d892019-08-16 09:27:01 +02003285 LY_CHECK_RET(!last->stmt, LY_EMEM);
David Sedláka82ecff2019-08-16 10:51:48 +02003286
3287 LY_CHECK_RET(lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic));
David Sedlákb1a78352019-06-28 16:16:29 +02003288 /* attributes with prefix are ignored */
3289 if (!temp_prefix) {
David Sedlák169cc522019-08-15 13:23:45 +02003290 INSERT_STRING(ctx->xml_ctx.ctx, last->arg, dynamic, out, out_len);
David Sedlákc005d892019-08-16 09:27:01 +02003291 LY_CHECK_RET(!last->arg, LY_EMEM);
David Sedláka82ecff2019-08-16 10:51:48 +02003292 } else {
3293 if (dynamic) {
3294 free(out);
3295 }
David Sedlákb1a78352019-06-28 16:16:29 +02003296 }
3297 }
3298
David Sedláka82ecff2019-08-16 10:51:48 +02003299 /* parse content of element if any */
3300 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3301 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
3302 if (ret == LY_EINVAL) {
3303 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3304 /* parse subelements */
3305 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len));
3306 if (!temp_name) {
3307 /* end of element reached */
3308 break;
3309 }
3310 LY_CHECK_RET(yin_parse_element_generic(ctx, name2fname(temp_name, temp_prefix_len),
3311 len2flen(temp_name_len, temp_prefix_len), data, &new));
3312 if (!(*element)->child) {
3313 /* save first */
3314 (*element)->child = new;
3315 } else {
3316 last->next = new;
3317 }
3318 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003319 }
David Sedláka82ecff2019-08-16 10:51:48 +02003320 } else {
3321 LY_CHECK_RET(ret);
3322 /* save element content */
3323 if (out_len != 0) {
3324 INSERT_STRING(ctx->xml_ctx.ctx, (*element)->arg, dynamic, out, out_len);
3325 LY_CHECK_RET(!(*element)->arg, LY_EMEM);
3326 }
David Sedlák169cc522019-08-15 13:23:45 +02003327
David Sedláka82ecff2019-08-16 10:51:48 +02003328 /* read closing tag */
3329 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len));
3330 }
David Sedlákb1a78352019-06-28 16:16:29 +02003331 }
3332
David Sedlákc005d892019-08-16 09:27:01 +02003333 return LY_SUCCESS;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003334}
3335
3336LY_ERR
David Sedlák4f03b932019-07-26 13:01:47 +02003337yin_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 +02003338{
David Sedlák81497a32019-08-13 16:56:26 +02003339 LY_ERR ret = LY_SUCCESS;
3340 struct yin_subelement *subelems = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003341
Radek Krejcid6b76452019-09-03 17:03:03 +02003342 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 +02003343 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003344 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3345 LY_STMT_ANYXML, &mod->data, 0,
3346 LY_STMT_AUGMENT, &mod->augments, 0,
3347 LY_STMT_CHOICE, &mod->data, 0,
3348 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3349 LY_STMT_CONTAINER, &mod->data, 0,
3350 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3351 LY_STMT_DEVIATION, &mod->deviations, 0,
3352 LY_STMT_EXTENSION, &mod->extensions, 0,
3353 LY_STMT_FEATURE, &mod->features, 0,
3354 LY_STMT_GROUPING, &mod->groupings, 0,
3355 LY_STMT_IDENTITY, &mod->identities, 0,
3356 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3357 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3358 LY_STMT_LEAF, &mod->data, 0,
3359 LY_STMT_LEAF_LIST, &mod->data, 0,
3360 LY_STMT_LIST, &mod->data, 0,
3361 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3362 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3363 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3364 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3365 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3366 LY_STMT_REVISION, &mod->revs, 0,
3367 LY_STMT_RPC, &mod->rpcs, 0,
3368 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3369 LY_STMT_USES, &mod->data, 0,
3370 LY_STMT_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3371 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003372 ));
3373
Radek Krejcid6b76452019-09-03 17:03:03 +02003374 ret = yin_parse_content(ctx, subelems, 28, data, LY_STMT_MODULE, NULL, &mod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003375 subelems_deallocator(28, subelems);
3376
3377 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003378}
3379
3380LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003381yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3382{
David Sedlák81497a32019-08-13 16:56:26 +02003383 LY_ERR ret = LY_SUCCESS;
3384 struct yin_subelement *subelems = NULL;
David Sedlák298ff6d2019-07-26 14:29:03 +02003385
Radek Krejcid6b76452019-09-03 17:03:03 +02003386 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 +02003387 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003388 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3389 LY_STMT_ANYXML, &submod->data, 0,
3390 LY_STMT_AUGMENT, &submod->augments, 0,
3391 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3392 LY_STMT_CHOICE, &submod->data, 0,
3393 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3394 LY_STMT_CONTAINER, &submod->data, 0,
3395 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3396 LY_STMT_DEVIATION, &submod->deviations, 0,
3397 LY_STMT_EXTENSION, &submod->extensions, 0,
3398 LY_STMT_FEATURE, &submod->features, 0,
3399 LY_STMT_GROUPING, &submod->groupings, 0,
3400 LY_STMT_IDENTITY, &submod->identities, 0,
3401 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3402 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3403 LY_STMT_LEAF, &submod->data, 0,
3404 LY_STMT_LEAF_LIST, &submod->data, 0,
3405 LY_STMT_LIST, &submod->data, 0,
3406 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3407 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3408 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3409 LY_STMT_REVISION, &submod->revs, 0,
3410 LY_STMT_RPC, &submod->rpcs, 0,
3411 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3412 LY_STMT_USES, &submod->data, 0,
3413 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3414 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003415 ));
3416
Radek Krejcid6b76452019-09-03 17:03:03 +02003417 ret = yin_parse_content(ctx, subelems, 27, data, LY_STMT_SUBMODULE, NULL, &submod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003418 subelems_deallocator(27, subelems);
3419
3420 return ret;
David Sedlák298ff6d2019-07-26 14:29:03 +02003421}
3422
3423LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02003424yin_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 +02003425{
Radek Krejcid6b76452019-09-03 17:03:03 +02003426 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003427 LY_ERR ret = LY_SUCCESS;
3428 const char *prefix, *name;
3429 size_t prefix_len, name_len;
3430 struct yin_arg_record *attrs = NULL;
3431 struct lysp_submodule *mod_p = NULL;
3432
3433 /* create context */
3434 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003435 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003436 (*yin_ctx)->xml_ctx.ctx = ctx;
3437 (*yin_ctx)->xml_ctx.line = 1;
3438
David Sedlák1b623122019-08-05 15:27:49 +02003439 /* map the typedefs and groupings list from main context to the submodule's context */
3440 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3441 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3442
David Sedlák8985a142019-07-31 16:43:06 +02003443 /* check submodule */
3444 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3445 LY_CHECK_GOTO(ret, cleanup);
3446 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3447 LY_CHECK_GOTO(ret, cleanup);
Radek Krejcid6b76452019-09-03 17:03:03 +02003448 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, LY_STMT_NONE);
David Sedlák8985a142019-07-31 16:43:06 +02003449
Radek Krejcid6b76452019-09-03 17:03:03 +02003450 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003451 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3452 ret = LY_EINVAL;
3453 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003454 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003455 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003456 ret = LY_EVALID;
3457 goto cleanup;
3458 }
3459
3460 mod_p = calloc(1, sizeof *mod_p);
3461 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3462 mod_p->parsing = 1;
3463
3464 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3465 LY_CHECK_GOTO(ret, cleanup);
3466
David Sedlák6d781b62019-08-02 15:22:52 +02003467 name = NULL;
David Sedlákbf8a2b72019-08-14 16:48:10 +02003468 /* skip possible trailing whitespaces at end of the input */
3469 while(*data && isspace(*data)) {
3470 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003471 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003472 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003473 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 +02003474 ret = LY_EVALID;
3475 goto cleanup;
3476 }
3477
David Sedlák8985a142019-07-31 16:43:06 +02003478 mod_p->parsing = 0;
3479 *submod = mod_p;
3480
3481cleanup:
3482 if (ret) {
3483 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003484 yin_parser_ctx_free(*yin_ctx);
3485 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003486 }
3487
3488 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3489 return ret;
3490}
3491
3492LY_ERR
3493yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003494{
David Sedláke4889912018-11-02 09:52:40 +01003495 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003496 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003497 struct lysp_module *mod_p = NULL;
3498 const char *prefix, *name;
3499 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003500 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003501
David Sedlák8985a142019-07-31 16:43:06 +02003502 /* create context */
3503 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003504 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003505 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
Radek Krejci335332a2019-09-05 13:03:35 +02003506 (*yin_ctx)->pos_type = LY_VLOG_LINE;
David Sedlák8985a142019-07-31 16:43:06 +02003507 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003508
David Sedlák8985a142019-07-31 16:43:06 +02003509 /* check module */
3510 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003511 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003512 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003513 LY_CHECK_GOTO(ret, cleanup);
Radek Krejcid6b76452019-09-03 17:03:03 +02003514 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, LY_STMT_NONE);
3515 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003516 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 +01003517 ret = LY_EINVAL;
3518 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003519 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003520 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003521 ret = LY_EVALID;
3522 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003523 }
3524
David Sedlák3017da42019-02-15 09:48:04 +01003525 /* allocate module */
3526 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003527 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003528 mod_p->mod = mod;
3529 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003530
David Sedlák00250342019-06-21 14:19:39 +02003531 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003532 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003533 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003534
David Sedlákbf8a2b72019-08-14 16:48:10 +02003535 name = NULL;
3536 /* skip possible trailing whitespaces at end of the input */
3537 while(*data && isspace(*data)) {
3538 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003539 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003540 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003541 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 +02003542 ret = LY_EVALID;
3543 goto cleanup;
3544 }
3545
David Sedlák3017da42019-02-15 09:48:04 +01003546 mod_p->parsing = 0;
3547 mod->parsed = mod_p;
3548
3549cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003550 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003551 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003552 yin_parser_ctx_free(*yin_ctx);
3553 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003554 }
David Sedlák8985a142019-07-31 16:43:06 +02003555 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003556 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003557}