blob: 21fb8d032a6723836f3a96ba4d863b8de3b80b0b [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/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200375 * @brief Get record with given 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 Krejci12b1c152019-09-05 16:20:48 +0200384get_record(enum ly_stmt type, size_t array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200385{
Radek Krejci12b1c152019-09-05 16:20:48 +0200386 for (unsigned int u = 0; u < array_size; ++u) {
387 if (array[u].type == type) {
388 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200389 }
390 }
David Sedlákd6e56892019-07-01 15:40:24 +0200391 return NULL;
392}
393
David Sedlákbba38e52019-07-09 15:20:01 +0200394/**
395 * @brief Helper function to check mandatory constraint of subelement.
396 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200397 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200398 * @param[in] subelem_info Array of information about subelements.
399 * @param[in] subelem_info_size Size of subelem_info array.
400 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
401 *
402 * @return LY_ERR values.
403 */
404static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200405yin_check_subelem_mandatory_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200406 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200407{
David Sedlákb0faad82019-07-04 14:28:59 +0200408 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200409 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200410 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200411 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200412 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200413 return LY_EVALID;
414 }
415 }
416
417 return LY_SUCCESS;
418}
419
David Sedlákbba38e52019-07-09 15:20:01 +0200420/**
421 * @brief Helper function to check "first" constraint of subelement.
422 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200423 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200424 * @param[in] subelem_info Array of information about subelements.
425 * @param[in] subelem_info_size Size of subelem_info array.
426 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200427 * @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 +0200428 *
429 * @return LY_ERR values.
430 */
431static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200432yin_check_subelem_first_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200433 signed char subelem_info_size, enum ly_stmt current_element,
David Sedláke1a30302019-07-10 13:49:38 +0200434 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200435{
David Sedlákb0faad82019-07-04 14:28:59 +0200436 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200437 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200438 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
439 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200440 return LY_EVALID;
441 }
442 }
443
444 return LY_SUCCESS;
445}
446
David Sedlákbba38e52019-07-09 15:20:01 +0200447/**
David Sedlákb4e44562019-07-04 15:42:12 +0200448 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
449 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200450 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200451 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200452 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákd6e56892019-07-01 15:40:24 +0200453 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákb4e44562019-07-04 15:42:12 +0200454 * @param[in] kw Type of current element.
455 * @param[out] value Where value of attribute should be stored.
456 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200457 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200458 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200459 *
David Sedlákd6e56892019-07-01 15:40:24 +0200460 * @return LY_ERR values.
461 */
David Sedlákb4e44562019-07-04 15:42:12 +0200462static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200463yin_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 +0200464 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 +0200465{
David Sedlák1f90d252019-07-10 17:09:32 +0200466 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200467 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200468 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200469 };
David Sedlákb4e44562019-07-04 15:42:12 +0200470
David Sedlákda8ffa32019-07-08 14:17:10 +0200471 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200472}
473
474/**
David Sedlák6542aed2019-08-14 10:47:43 +0200475 * @brief Parse path element.
476 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200477 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200478 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
479 * @param[in,out] data Data to read from, always moved to currently handled character.
480 * @param[in] kw Type of current element.
481 * @param[out] type Type structure to store parsed value, flags and extension instances.
482 *
483 * @return LY_ERR values.
484 */
485static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200486yin_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 +0200487 struct lysp_type *type)
488{
489 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
490 YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
491 type->flags |= LYS_SET_PATH;
492
493 return LY_SUCCESS;
494}
495
496/**
David Sedlákd3983112019-07-12 11:20:56 +0200497 * @brief Parse pattern element.
498 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200499 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd3983112019-07-12 11:20:56 +0200500 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
501 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200502 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200503 *
504 * @return LY_ERR values.
505 */
506static LY_ERR
507yin_parse_pattern(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
508 struct lysp_type *type)
509{
510 const char *real_value = NULL;
511 char *saved_value = NULL;
512 struct lysp_restr *restr;
513
514 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->patterns, restr, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200515 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 +0200516 size_t len = strlen(real_value);
517
518 saved_value = malloc(len + 2);
519 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
520 memmove(saved_value + 1, real_value, len);
521 FREE_STRING(ctx->xml_ctx.ctx, real_value);
522 saved_value[0] = 0x06;
523 saved_value[len + 1] = '\0';
524 restr->arg = lydict_insert_zc(ctx->xml_ctx.ctx, saved_value);
525 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
526 type->flags |= LYS_SET_PATTERN;
527
528 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200529 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
530 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
531 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
532 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
533 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
534 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákd3983112019-07-12 11:20:56 +0200535 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200536 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200537}
538
David Sedlákc5b20842019-08-13 10:18:31 +0200539/**
540 * @brief Parse fraction-digits element.
541 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200542 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200543 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
544 * @param[in,out] data Data to read from, always moved to currently handled character.
545 * @param[in,out] type Type structure to store value, flags and extension instances.
546 *
547 * @return LY_ERR values.
548 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200549static LY_ERR
550yin_parse_fracdigits(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
551 struct lysp_type *type)
552{
553 const char *temp_val = NULL;
554 char *ptr;
555 unsigned long int num;
556
Radek Krejcid6b76452019-09-03 17:03:03 +0200557 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 +0200558
559 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200560 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200561 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
562 return LY_EVALID;
563 }
564
565 errno = 0;
566 num = strtoul(temp_val, &ptr, 10);
567 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200568 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200569 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
570 return LY_EVALID;
571 }
572 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200573 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200574 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
575 return LY_EVALID;
576 }
David Sedlák2ab5d8e2019-07-16 11:19:41 +0200577 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200578 type->fraction_digits = num;
579 type->flags |= LYS_SET_FRDIGITS;
580 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200581 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200582 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200583 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200584}
585
David Sedlák07869a52019-07-12 14:28:19 +0200586/**
David Sedlák43801c92019-08-05 15:58:54 +0200587 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200588 *
589 * @param[in,out] ctx YIN parser context for logging and to store current state.
590 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
591 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200592 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200593 *
594 * @return LY_ERR values.
595 */
David Sedlákca36c422019-07-12 12:47:55 +0200596static LY_ERR
David Sedlák43801c92019-08-05 15:58:54 +0200597yin_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 +0200598{
David Sedlák07869a52019-07-12 14:28:19 +0200599 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200600
David Sedlák43801c92019-08-05 15:58:54 +0200601 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->enums, en, LY_EMEM);
602 type->flags |= LYS_SET_ENUM;
David Sedláke6284fc2019-09-10 11:57:02 +0200603 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_STR_ARG, LY_STMT_ENUM));
David Sedlák43801c92019-08-05 15:58:54 +0200604 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
605 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
606 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200607
608 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200609 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
610 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
611 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
612 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
613 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
614 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákca36c422019-07-12 12:47:55 +0200615 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200616 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200617}
618
619/**
620 * @brief Parse bit element.
621 *
622 * @param[in,out] ctx YIN parser context for logging and to store current state.
623 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
624 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200625 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200626 *
627 * @return LY_ERR values.
628 */
629static LY_ERR
630yin_parse_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
631 struct lysp_type *type)
632{
633 struct lysp_type_enum *en;
634
635 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->bits, en, LY_EMEM);
636 type->flags |= LYS_SET_BIT;
Radek Krejcid6b76452019-09-03 17:03:03 +0200637 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 +0200638 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
639
640 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200641 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
642 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
643 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
644 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
645 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
646 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák43801c92019-08-05 15:58:54 +0200647 };
Radek Krejcid6b76452019-09-03 17:03:03 +0200648 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200649}
650
David Sedlákd3983112019-07-12 11:20:56 +0200651/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200652 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
653 * more instances, such as base or if-feature.
654 *
655 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200656 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200657 * @param[in,out] data Data to read from, always moved to currently handled character.
658 * @param[in] kw Type of current element.
659 * @param[out] values Parsed values to add to.
660 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200661 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200662 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200663 *
664 * @return LY_ERR values.
665 */
666static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200667yin_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 +0200668 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 +0200669{
670 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200671 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200672 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200673 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200674 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200675 };
676
David Sedlák1f90d252019-07-10 17:09:32 +0200677 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200678
679 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
680}
681
682/**
David Sedlák6542aed2019-08-14 10:47:43 +0200683 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
684 *
685 * @param[in,out] ctx YIN parser context for logging and to store current state.
686 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
687 * @param[in,out] data Data to read from, always moved to currently handled character.
688 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200689 * @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 +0200690 * @param[in] arg_type Expected type of attribute.
691 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200692 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200693 *
694 * @return LY_ERR values.
695 */
696static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200697yin_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 +0200698 struct yin_subelement *subinfo, enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
699{
700 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
701 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subinfo->dest,
702 arg_type, arg_val_type, exts));
703 } else {
704 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subinfo->dest,
705 arg_type, arg_val_type, exts));
706 }
707
708 return LY_SUCCESS;
709}
710
711/**
712 * @brief Parse base element.
713 *
714 * @param[in,out] ctx YIN parser context for logging and to store current state.
715 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
716 * @param[in,out] data Data to read from, always moved to currently handled character.
717 * @param[in] parent Identification of parent element.
718 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200719 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200720 *
721 * @return LY_ERR values.
722 */
723static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200724yin_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 +0200725 void *dest, struct lysp_ext_instance **exts)
726{
727 struct lysp_type *type = NULL;
728
Radek Krejcid6b76452019-09-03 17:03:03 +0200729 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200730 type = (struct lysp_type *)dest;
Radek Krejcid6b76452019-09-03 17:03:03 +0200731 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 +0200732 Y_PREF_IDENTIF_ARG, exts));
733 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200734 } else if (parent == LY_STMT_IDENTITY) {
735 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, LY_STMT_BASE, (const char ***)dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200736 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
737 } else {
738 LOGINT(ctx->xml_ctx.ctx);
739 return LY_EINT;
740 }
741
742 return LY_SUCCESS;
743}
744
745/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200746 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200747 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200748 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákcf5569a2019-07-11 13:31:34 +0200749 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
750 * @param[in,out] data Data to read from, always moved to currently handled character.
751 * @prama[out] type Type structure to store value, flag and extensions.
752 *
753 * @return LY_ERR values.
754 */
755static LY_ERR
756yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
757 const char **data, struct lysp_type *type)
758{
759 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200760 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200761 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200762 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200763
764 type->flags |= LYS_SET_REQINST;
Radek Krejcid6b76452019-09-03 17:03:03 +0200765 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 +0200766 if (strcmp(temp_val, "true") == 0) {
767 type->require_instance = 1;
768 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200769 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
770 "require-instance", "true", "false");
David Sedlákcf5569a2019-07-11 13:31:34 +0200771 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
772 return LY_EVALID;
773 }
774 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
775
Radek Krejcid6b76452019-09-03 17:03:03 +0200776 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200777}
778
779/**
David Sedlákce77bf52019-07-11 16:59:31 +0200780 * @brief Parse modifier element.
781 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200782 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200783 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
784 * @param[in,out] data Data to read from, always moved to currently handled character.
785 * @param[in,out] pat Value to write to.
786 * @param[in,out] exts Extension instances to add to.
787 *
788 * @return LY_ERR values.
789 */
790static LY_ERR
791yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
792 const char **pat, struct lysp_ext_instance **exts)
793{
David Sedlákd3983112019-07-12 11:20:56 +0200794 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200795 const char *temp_val;
796 char *modified_val;
797 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200798 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákce77bf52019-07-11 16:59:31 +0200799 };
800
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_MODIFIER));
David Sedlákce77bf52019-07-11 16:59:31 +0200802 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200803 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
804 "modifier", "invert-match");
David Sedlákce77bf52019-07-11 16:59:31 +0200805 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
806 return LY_EVALID;
807 }
David Sedlákd3983112019-07-12 11:20:56 +0200808 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200809
810 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200811 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200812 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200813 strcpy(modified_val, *pat);
814 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200815
816 /* modify the new value */
817 modified_val[0] = 0x15;
818 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
819
Radek Krejcid6b76452019-09-03 17:03:03 +0200820 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200821}
822
823/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200824 * @brief Parse a restriction element (length, range or one instance of must).
825 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200826 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb7296dd2019-07-11 14:58:38 +0200827 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
828 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejcid6b76452019-09-03 17:03:03 +0200829 * @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 +0200830 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200831 */
832static LY_ERR
833yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +0200834 enum ly_stmt restr_kw, struct lysp_restr *restr)
David Sedlákb7296dd2019-07-11 14:58:38 +0200835{
Radek Krejcid6b76452019-09-03 17:03:03 +0200836 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
David Sedlákb7296dd2019-07-11 14:58:38 +0200837 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200838 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
839 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
840 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
841 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
842 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200843 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200844 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200845 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200846 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
847
848 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
849}
850
851/**
David Sedlák6542aed2019-08-14 10:47:43 +0200852 * @brief Parse range element.
853 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200854 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200855 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
856 * @param[in,out] data Data to read from, always moved to currently handled character.
857 * @param[out] type Type structure to store parsed value and flags.
858 *
859 * @return LY_ERR values.
860 */
861static LY_ERR
862yin_parse_range(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
863 const char **data, struct lysp_type *type)
864{
865 type->range = calloc(1, sizeof *type->range);
866 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200867 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, LY_STMT_RANGE, type->range));
David Sedlák6542aed2019-08-14 10:47:43 +0200868 type->flags |= LYS_SET_RANGE;
869
870 return LY_SUCCESS;
871}
872
873/**
874 * @brief Parse length element.
875 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200876 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200877 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
878 * @param[in,out] data Data to read from, always moved to currently handled character.
879 * @param[out] type Type structure to store parsed value and flags.
880 *
881 * @return LY_ERR values.
882 */
883static LY_ERR
884yin_parse_length(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
885 const char **data, struct lysp_type *type)
886{
887 type->length = calloc(1, sizeof *type->length);
888 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200889 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200890 type->flags |= LYS_SET_LENGTH;
891
892 return LY_SUCCESS;
893}
894
895/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200896 * @brief Parse must element.
897 *
898 * @param[in,out] ctx YIN parser context for logging and to store current state.
899 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
900 * @param[in,out] data Data to read from, always moved to currently handled character.
901 * @param[in,out] restrs Restrictions to add to.
902 *
903 * @return LY_ERR values.
904 */
905static LY_ERR
906yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
907{
908 struct lysp_restr *restr;
909
910 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +0200911 return yin_parse_restriction(ctx, attrs, data, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200912}
913
914/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200915 * @brief Parse position or value element.
916 *
917 * @param[in,out] ctx YIN parser context for logging and to store current state.
918 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
919 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejcid6b76452019-09-03 17:03:03 +0200920 * @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 +0200921 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200922 *
923 * @return LY_ERR values.
924 */
925static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +0200926yin_parse_value_pos(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +0200927 enum ly_stmt kw, struct lysp_type_enum *enm)
David Sedlák5545f5d2019-07-11 11:55:16 +0200928{
Radek Krejcid6b76452019-09-03 17:03:03 +0200929 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +0200930 const char *temp_val = NULL;
931 char *ptr;
932 long int num;
933 unsigned long int unum;
934
935 /* set value flag */
936 enm->flags |= LYS_SET_VALUE;
937
938 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200939 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 +0200940 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
Radek Krejcid6b76452019-09-03 17:03:03 +0200941 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200942 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 +0200943 goto error;
944 }
945
946 /* convert value */
947 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +0200948 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200949 num = strtol(temp_val, &ptr, 10);
950 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200951 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 +0200952 goto error;
953 }
954 } else {
955 unum = strtoul(temp_val, &ptr, 10);
956 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200957 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 +0200958 goto error;
959 }
960 }
961 /* check if whole argument value was converted */
962 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200963 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 +0200964 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200965 }
966 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +0200967 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 +0200968 goto error;
969 }
970 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +0200971 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200972 enm->value = num;
973 } else {
974 enm->value = unum;
975 }
976 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
977
978 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200979 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200980 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200981 };
David Sedlák5545f5d2019-07-11 11:55:16 +0200982 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
983
David Sedlákbf8a2b72019-08-14 16:48:10 +0200984error:
David Sedlák5545f5d2019-07-11 11:55:16 +0200985 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
986 return LY_EVALID;
987}
988
David Sedlák05404f62019-07-24 14:11:53 +0200989
990/**
991 * @brief Parse belongs-to element.
992 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200993 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +0200994 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
995 * @param[in,out] data Data to read from, always moved to currently handled character.
996 * @param[out] submod Structure of submodule that is being parsed.
997 * @param[in,out] exts Extension instances to add to.
998 *
999 * @return LY_ERR values
1000 */
1001static LY_ERR
1002yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1003 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
1004{
1005 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001006 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1007 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák05404f62019-07-24 14:11:53 +02001008 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001009 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 +02001010
Radek Krejcid6b76452019-09-03 17:03:03 +02001011 return yin_parse_content(ctx, subelems, 2, data, LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001012}
1013
David Sedlák5545f5d2019-07-11 11:55:16 +02001014/**
David Sedlákc1771b12019-07-10 15:55:46 +02001015 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001016 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001017 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001018 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001019 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákcf5569a2019-07-11 13:31:34 +02001020 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejcid6b76452019-09-03 17:03:03 +02001021 * @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 +02001022 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001023 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001024 *
1025 * @return LY_ERR values.
1026 */
1027static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001028yin_parse_meta(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001029 enum ly_stmt elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +02001030{
Radek Krejcid6b76452019-09-03 17:03:03 +02001031 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 +02001032
David Sedlák968ac342019-07-11 15:17:59 +02001033 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001034 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1035 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +02001036 };
David Sedlákdf2a9732019-08-07 13:23:16 +02001037 /* check attributes */
1038 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 +02001039
David Sedlákdf2a9732019-08-07 13:23:16 +02001040 /* parse content */
David Sedlákda8ffa32019-07-08 14:17:10 +02001041 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001042}
1043
1044/**
David Sedlákc1771b12019-07-10 15:55:46 +02001045 * @brief Parse error-message element.
1046 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001047 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001048 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákc1771b12019-07-10 15:55:46 +02001049 * @param[in,out] data Data to read from.
1050 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001051 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001052 *
1053 * @return LY_ERR values.
1054 */
1055static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001056yin_parse_err_msg(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdf2a9732019-08-07 13:23:16 +02001057 const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +02001058{
David Sedlák968ac342019-07-11 15:17:59 +02001059 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001060 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1061 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +02001062 };
David Sedlákc1771b12019-07-10 15:55:46 +02001063
David Sedlákdf2a9732019-08-07 13:23:16 +02001064 /* check attributes */
David Sedláke6284fc2019-09-10 11:57:02 +02001065 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_STR_ARG, LY_STMT_ERROR_MESSAGE));
David Sedlákdf2a9732019-08-07 13:23:16 +02001066
Radek Krejcid6b76452019-09-03 17:03:03 +02001067 return yin_parse_content(ctx, subelems, 2, data, LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001068}
1069
1070/**
David Sedlák6542aed2019-08-14 10:47:43 +02001071 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001072 *
1073 * @param[in,out] ctx YIN parser context for logging and to store current state.
1074 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1075 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák6542aed2019-08-14 10:47:43 +02001076 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001077 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001078 *
1079 * @return LY_ERR values.
1080 */
1081static LY_ERR
David Sedlák6542aed2019-08-14 10:47:43 +02001082yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001083 enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001084{
David Sedlák6542aed2019-08-14 10:47:43 +02001085 struct lysp_type *type = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +02001086 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001087 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
1088 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1089 type = *((struct lysp_type **)subinfo->dest);
1090 } else {
1091 type = (struct lysp_type *)subinfo->dest;
1092 }
1093 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001094 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001095 struct lysp_type *nested_type = NULL;
1096 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->types, nested_type, LY_EMEM);
1097 type->flags |= LYS_SET_TYPE;
1098 type = nested_type;
1099 }
David Sedlák374d2b32019-07-17 15:06:55 +02001100 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001101 {LY_STMT_BASE, type, 0},
1102 {LY_STMT_BIT, type, 0},
1103 {LY_STMT_ENUM, type, 0},
1104 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1105 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1106 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1107 {LY_STMT_PATTERN, type, 0},
1108 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1109 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1110 {LY_STMT_TYPE, type},
1111 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák374d2b32019-07-17 15:06:55 +02001112 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001113 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1114 return yin_parse_content(ctx, subelems, 11, data, LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001115}
1116
David Sedlák1af868e2019-07-17 17:03:14 +02001117/**
1118 * @brief Parse max-elements element.
1119 *
1120 * @param[in,out] ctx YIN parser context for logging and to store current state.
1121 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1122 * @param[in,out] data Data to read from, always moved to currently handled character.
1123 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001124 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001125 * @param[in,out] exts Extension instances to add to.
1126 *
1127 * @return LY_ERR values.
1128 */
1129static LY_ERR
1130yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
1131 uint16_t *flags, struct lysp_ext_instance **exts)
1132{
1133 const char *temp_val = NULL;
1134 char *ptr;
1135 unsigned long int num;
1136 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001137 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák1af868e2019-07-17 17:03:14 +02001138 };
David Sedlák374d2b32019-07-17 15:06:55 +02001139
David Sedlák1af868e2019-07-17 17:03:14 +02001140 *flags |= LYS_SET_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02001141 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 +02001142 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 +02001143 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001144 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1145 return LY_EVALID;
1146 }
1147
1148 if (strcmp(temp_val, "unbounded")) {
1149 errno = 0;
1150 num = strtoul(temp_val, &ptr, 10);
1151 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001152 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001153 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1154 return LY_EVALID;
1155 }
1156 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001157 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001158 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1159 return LY_EVALID;
1160 }
1161 *max = num;
1162 }
1163 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
Radek Krejcid6b76452019-09-03 17:03:03 +02001164 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001165}
David Sedlák374d2b32019-07-17 15:06:55 +02001166
1167/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001168 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001169 *
1170 * @param[in,out] ctx YIN parser context for logging and to store current state.
1171 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1172 * @param[in,out] data Data to read from, always moved to currently handled character.
1173 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001174 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001175 * @param[in,out] exts Extension instances to add to.
1176 *
1177 * @return LY_ERR values.
1178 */
1179static LY_ERR
1180yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
1181 uint16_t *flags, struct lysp_ext_instance **exts)
1182{
1183 const char *temp_val = NULL;
1184 char *ptr;
1185 unsigned long int num;
1186 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001187 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák09e18c92019-07-18 11:17:11 +02001188 };
1189
1190 *flags |= LYS_SET_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02001191 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 +02001192
1193 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001194 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001195 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1196 return LY_EVALID;
1197 }
1198
1199 errno = 0;
1200 num = strtoul(temp_val, &ptr, 10);
1201 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001202 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001203 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1204 return LY_EVALID;
1205 }
1206 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001207 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001208 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1209 return LY_EVALID;
1210 }
1211 *min = num;
1212 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
Radek Krejcid6b76452019-09-03 17:03:03 +02001213 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001214}
1215
David Sedláka2dad212019-07-18 12:45:19 +02001216/**
1217 * @brief Parse min-elements or max-elements element.
1218 *
1219 * @param[in,out] ctx YIN parser context for logging and to store current state.
1220 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1221 * @param[in,out] data Data to read from, always moved to currently handled character.
1222 * @param[in] parent Identification of parent element.
1223 * @param[in] current Identification of current element.
1224 * @param[in] dest Where the parsed value and flags should be stored.
1225 *
1226 * @return LY_ERR values.
1227 */
David Sedlák09e18c92019-07-18 11:17:11 +02001228static LY_ERR
1229yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001230 enum ly_stmt parent, enum ly_stmt current, void *dest)
David Sedlák09e18c92019-07-18 11:17:11 +02001231{
Radek Krejcid6b76452019-09-03 17:03:03 +02001232 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1233 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 +02001234 uint32_t *lim;
1235 uint16_t *flags;
1236 struct lysp_ext_instance **exts;
1237
Radek Krejcid6b76452019-09-03 17:03:03 +02001238 if (parent == LY_STMT_LEAF_LIST) {
1239 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 +02001240 flags = &((struct lysp_node_leaflist *)dest)->flags;
1241 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001242 } else if (parent == LY_STMT_REFINE) {
1243 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001244 flags = &((struct lysp_refine *)dest)->flags;
1245 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001246 } else if (parent == LY_STMT_LIST) {
1247 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 +02001248 flags = &((struct lysp_node_list *)dest)->flags;
1249 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001250 } else {
1251 lim = ((struct minmax_dev_meta *)dest)->lim;
1252 flags = ((struct minmax_dev_meta *)dest)->flags;
1253 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001254 }
1255
Radek Krejcid6b76452019-09-03 17:03:03 +02001256 if (current == LY_STMT_MAX_ELEMENTS) {
David Sedlák09e18c92019-07-18 11:17:11 +02001257 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1258 } else {
1259 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1260 }
1261
1262 return LY_SUCCESS;
1263}
1264
1265/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001266 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001267 *
1268 * @param[in,out] ctx YIN parser context for logging and to store current state.
1269 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1270 * @param[in,out] data Data to read from, always moved to currently handled character.
1271 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001272 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001273 *
1274 * @return LY_ERR values.
1275 */
1276static LY_ERR
1277yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1278 uint16_t *flags, struct lysp_ext_instance **exts)
1279{
1280 const char *temp_val;
1281 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001282 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedláka2dad212019-07-18 12:45:19 +02001283 };
1284
Radek Krejcid6b76452019-09-03 17:03:03 +02001285 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 +02001286 if (strcmp(temp_val, "system") == 0) {
1287 *flags |= LYS_ORDBY_SYSTEM;
1288 } else if (strcmp(temp_val, "user") == 0) {
1289 *flags |= LYS_ORDBY_USER;
1290 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001291 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1292 "ordered-by", "system", "user");
David Sedláka2dad212019-07-18 12:45:19 +02001293 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1294 return LY_EVALID;
1295 }
1296 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1297
Radek Krejcid6b76452019-09-03 17:03:03 +02001298 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001299}
1300
1301/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001302 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +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.
Radek Krejcid6b76452019-09-03 17:03:03 +02001307 * @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 +02001308 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001309 *
1310 * @return LY_ERR values.
1311 */
1312static LY_ERR
1313yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
Radek Krejcid6b76452019-09-03 17:03:03 +02001314 enum ly_stmt any_kw, struct tree_node_meta *node_meta)
David Sedlák8a83bbb2019-07-18 14:46:00 +02001315{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001316 struct lysp_node_anydata *any;
1317
David Sedlák8d552d62019-08-06 15:29:05 +02001318 /* create new sibling */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001319 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, any, next);
Radek Krejcid6b76452019-09-03 17:03:03 +02001320 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001321 any->parent = node_meta->parent;
1322
David Sedlákbf8a2b72019-08-14 16:48:10 +02001323 /* parse argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001324 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 +02001325
1326 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001327 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1328 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1329 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1330 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1331 {LY_STMT_MUST, &any->musts, 0},
1332 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1333 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1334 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1335 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8a83bbb2019-07-18 14:46:00 +02001336 };
1337 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1338}
1339
1340/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001341 * @brief parse leaf element.
1342 *
1343 * @param[in,out] ctx YIN parser context for logging and to store current state.
1344 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1345 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001346 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001347 *
1348 * @return LY_ERR values.
1349 */
1350static LY_ERR
1351yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1352 struct tree_node_meta *node_meta)
1353{
David Sedlák203ca3a2019-07-18 15:26:25 +02001354 struct lysp_node_leaf *leaf;
1355
David Sedlák8d552d62019-08-06 15:29:05 +02001356 /* create structure new leaf */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001357 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, leaf, next);
David Sedlák203ca3a2019-07-18 15:26:25 +02001358 leaf->nodetype = LYS_LEAF;
1359 leaf->parent = node_meta->parent;
1360
David Sedlák203ca3a2019-07-18 15:26:25 +02001361 /* parser argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001362 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 +02001363
1364 /* parse content */
1365 struct yin_subelement subelems[12] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001366 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1367 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1368 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1369 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1370 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1371 {LY_STMT_MUST, &leaf->musts, 0},
1372 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1373 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1374 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1375 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1376 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1377 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001378 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001379 return yin_parse_content(ctx, subelems, 12, data, LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001380}
1381
1382/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001383 * @brief Parse leaf-list element.
1384 *
1385 * @param[in,out] ctx YIN parser context for logging and to store current state.
1386 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1387 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001388 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001389 *
1390 * @return LY_ERR values.
1391 */
1392static LY_ERR
1393yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1394 struct tree_node_meta *node_meta)
1395{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001396 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001397
David Sedlákbf8a2b72019-08-14 16:48:10 +02001398 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, llist, next);
David Sedlák8d552d62019-08-06 15:29:05 +02001399
David Sedlákc3da3ef2019-07-19 12:56:08 +02001400 llist->nodetype = LYS_LEAFLIST;
1401 llist->parent = node_meta->parent;
1402
David Sedlákc3da3ef2019-07-19 12:56:08 +02001403 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001404 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 +02001405
1406 /* parse content */
1407 struct yin_subelement subelems[14] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001408 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1409 {LY_STMT_DEFAULT, &llist->dflts, 0},
1410 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1411 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1412 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1413 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1414 {LY_STMT_MUST, &llist->musts, 0},
1415 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1416 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1417 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1418 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1419 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1420 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1421 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001422 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001423 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 +02001424
David Sedlákbf8a2b72019-08-14 16:48:10 +02001425 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001426 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001427 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001428 return LY_EVALID;
1429 }
1430 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001431 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001432 return LY_EVALID;
1433 }
1434
1435 return LY_SUCCESS;
1436}
1437
1438/**
David Sedlák04e17b22019-07-19 15:29:48 +02001439 * @brief Parse typedef element.
1440 *
1441 * @param[in,out] ctx YIN parser context for logging and to store current state.
1442 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1443 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001444 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001445 *
1446 * @return LY_ERR values.
1447 */
1448static LY_ERR
1449yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02001450 struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001451{
1452 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001453 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
David Sedlák6881b512019-08-13 12:52:00 +02001454 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001455
1456 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001457 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 +02001458
1459 /* parse content */
1460 struct yin_subelement subelems[7] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001461 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1462 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1463 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1464 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1465 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1466 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1467 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001468 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001469 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001470
1471 /* store data for collision check */
1472 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
David Sedláke8b74df2019-08-14 14:18:22 +02001473 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0) == -1, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001474 }
1475
1476 return LY_SUCCESS;
1477}
1478
1479/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001480 * @brief Parse refine element.
1481 *
1482 * @param[in,out] ctx YIN parser context for logging and to store current state.
1483 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1484 * @param[in,out] data Data to read from, always moved to currently handled character.
1485 * @param[in,out] refines Refines to add to.
1486 *
1487 * @return LY_ERR values.
1488 */
1489static LY_ERR
1490yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1491 struct lysp_refine **refines)
1492{
1493 struct lysp_refine *rf;
1494
1495 /* allocate new refine */
1496 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1497
1498 /* parse attribute */
Radek Krejcid6b76452019-09-03 17:03:03 +02001499 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 +02001500 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1501
1502 /* parse content */
1503 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001504 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1505 {LY_STMT_DEFAULT, &rf->dflts, 0},
1506 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1507 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
1508 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1509 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1510 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1511 {LY_STMT_MUST, &rf->musts, 0},
1512 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1513 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1514 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001515 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001516 return yin_parse_content(ctx, subelems, 11, data, LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001517}
1518
1519/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001520 * @brief Parse uses element.
1521 *
1522 * @param[in,out] ctx YIN parser context for logging and to store current state.
1523 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1524 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001525 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001526 *
1527 * @return LY_ERR values.
1528 */
1529static LY_ERR
1530yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1531 struct tree_node_meta *node_meta)
1532{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001533 struct lysp_node_uses *uses;
1534
David Sedlák8d552d62019-08-06 15:29:05 +02001535 /* create new uses */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001536 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, uses, next);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001537 uses->nodetype = LYS_USES;
1538 uses->parent = node_meta->parent;
1539
David Sedlák0d6de5a2019-07-22 13:25:44 +02001540 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001541 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 +02001542
1543 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001544 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001545 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001546 {LY_STMT_AUGMENT, &augments, 0},
1547 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1548 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1549 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1550 {LY_STMT_REFINE, &uses->refines, 0},
1551 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1552 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1553 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001554 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001555 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001556 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1557
1558 return LY_SUCCESS;
1559}
1560
1561/**
David Sedlákaa854b02019-07-22 14:17:10 +02001562 * @brief Parse revision element.
1563 *
1564 * @param[in,out] ctx YIN parser context for logging and to store current state.
1565 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1566 * @param[in,out] data Data to read from, always moved to currently handled character.
1567 * @param[in,out] revs Parsed revisions to add to.
1568 *
1569 * @return LY_ERR values.
1570 */
1571static LY_ERR
1572yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1573 struct lysp_revision **revs)
1574{
1575 struct lysp_revision *rev;
1576 const char *temp_date = NULL;
1577
1578 /* allocate new reivison */
1579 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1580
1581 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001582 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 +02001583 /* check value */
1584 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1585 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1586 return LY_EVALID;
1587 }
1588 strcpy(rev->date, temp_date);
1589 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1590
1591 /* parse content */
1592 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001593 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1594 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1595 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001596 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001597 return yin_parse_content(ctx, subelems, 3, data, LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001598}
1599
David Sedlák5e13dea2019-07-22 16:06:45 +02001600/**
1601 * @brief Parse include element.
1602 *
1603 * @param[in,out] ctx YIN parser context for logging and to store current state.
1604 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1605 * @param[in,out] data Data to read from, always moved to currently handled character.
1606 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1607 *
1608 * @return LY_ERR values.
1609 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001610static LY_ERR
1611yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1612 struct include_meta *inc_meta)
1613{
1614 struct lysp_include *inc;
1615
1616 /* allocate new include */
1617 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1618
1619 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001620 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 +02001621
1622 /* submodules share the namespace with the module names, so there must not be
1623 * a module of the same name in the context, no need for revision matching */
1624 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 +02001625 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001626 return LY_EVALID;
1627 }
1628
1629 /* parse content */
1630 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001631 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1632 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1633 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1634 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák0c2bab92019-07-22 15:33:19 +02001635 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001636 return yin_parse_content(ctx, subelems, 4, data, LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001637}
1638
David Sedlákaa854b02019-07-22 14:17:10 +02001639/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001640 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001641 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001642 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001643 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of revision-date element.
1644 * @param[in,out] data Data to read from, always moved to currently handled character.
1645 * @param[in,out] rev Array to store the parsed value in.
1646 * @param[in,out] exts Extension instances to add to.
1647 *
1648 * @return LY_ERR values.
1649 */
1650static LY_ERR
1651yin_parse_revision_date(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, char *rev,
1652 struct lysp_ext_instance **exts)
1653{
1654 const char *temp_rev;
1655 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001656 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001657 };
1658
Radek Krejcid6b76452019-09-03 17:03:03 +02001659 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 +02001660 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
1661 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
1662
1663 strcpy(rev, temp_rev);
1664 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
1665
Radek Krejcid6b76452019-09-03 17:03:03 +02001666 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001667}
1668
1669/**
1670 * @brief Parse config element.
1671 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001672 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001673 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1674 * @param[in,out] data Data to read from, always moved to currently handled character.
1675 * @param[in,out] flags Flags to add to.
1676 * @param[in,out] exts Extension instances to add to.
1677 *
1678 * @return LY_ERR values.
1679 */
1680static LY_ERR
1681yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1682 struct lysp_ext_instance **exts)
1683{
1684 const char *temp_val = NULL;
1685 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001686 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001687 };
1688
Radek Krejcid6b76452019-09-03 17:03:03 +02001689 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 +02001690 if (strcmp(temp_val, "true") == 0) {
1691 *flags |= LYS_CONFIG_W;
1692 } else if (strcmp(temp_val, "false") == 0) {
1693 *flags |= LYS_CONFIG_R;
1694 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001695 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
1696 "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001697 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1698 return LY_EVALID;
1699 }
1700 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1701
Radek Krejcid6b76452019-09-03 17:03:03 +02001702 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001703}
1704
1705/**
1706 * @brief Parse yang-version 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 yang-version element.
1710 * @param[in] data Data to read from, always moved to currently handled character.
1711 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001712 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001713 *
1714 * @return LY_ERR values.
1715 */
1716static LY_ERR
1717yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
1718 struct lysp_ext_instance **exts)
1719{
1720 const char *temp_version = 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_version, Y_STR_ARG, LY_STMT_YANG_VERSION));
David Sedlákdfbbb442019-08-06 16:33:21 +02001726 if (strcmp(temp_version, "1.0") == 0) {
1727 *version = LYS_VERSION_1_0;
1728 } else if (strcmp(temp_version, "1.1") == 0) {
1729 *version = LYS_VERSION_1_1;
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_version, "value",
1732 "yang-version", "1.0", "1.1");
David Sedlákdfbbb442019-08-06 16:33:21 +02001733 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1734 return LY_EVALID;
1735 }
1736 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1737 ctx->mod_version = *version;
1738
Radek Krejcid6b76452019-09-03 17:03:03 +02001739 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001740}
1741
1742/**
1743 * @brief Parse import element.
1744 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001745 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001746 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1747 * @param[in,out] data Data to read from, always moved to currently handled character.
1748 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1749 *
1750 * @return LY_ERR values.
1751 */
1752static LY_ERR
1753yin_parse_import(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct import_meta *imp_meta)
1754{
1755 struct lysp_import *imp;
1756 /* allocate new element in sized array for import */
1757 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
1758
1759 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001760 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1761 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1762 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1763 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1764 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001765 };
1766
1767 /* parse import attributes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001768 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
1769 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001770 /* check prefix validity */
1771 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1772
1773 return LY_SUCCESS;
1774}
1775
1776/**
1777 * @brief Parse mandatory element.
1778 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001779 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001780 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1781 * @param[in,out] data Data to read from, always moved to currently handled character.
1782 * @param[in,out] flags Flags to add to.
1783 * @param[in,out] exts Extension instances to add to.
1784 *
1785 * @return LY_ERR values.
1786 */
1787static LY_ERR
1788yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1789 struct lysp_ext_instance **exts)
1790{
1791 const char *temp_val = NULL;
1792 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001793 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001794 };
1795
Radek Krejcid6b76452019-09-03 17:03:03 +02001796 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 +02001797 if (strcmp(temp_val, "true") == 0) {
1798 *flags |= LYS_MAND_TRUE;
1799 } else if (strcmp(temp_val, "false") == 0) {
1800 *flags |= LYS_MAND_FALSE;
1801 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001802 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1803 "mandatory", "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001804 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1805 return LY_EVALID;
1806 }
1807 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1808
Radek Krejcid6b76452019-09-03 17:03:03 +02001809 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001810}
1811
1812/**
1813 * @brief Parse status 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_status(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 *value = 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, &value, Y_STR_ARG, LY_STMT_STATUS));
David Sedlákdfbbb442019-08-06 16:33:21 +02001833 if (strcmp(value, "current") == 0) {
1834 *flags |= LYS_STATUS_CURR;
1835 } else if (strcmp(value, "deprecated") == 0) {
1836 *flags |= LYS_STATUS_DEPRC;
1837 } else if (strcmp(value, "obsolete") == 0) {
1838 *flags |= LYS_STATUS_OBSLT;
1839 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001840 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
1841 "status", "current", "deprecated", "obsolete");
David Sedlákdfbbb442019-08-06 16:33:21 +02001842 FREE_STRING(ctx->xml_ctx.ctx, value);
1843 return LY_EVALID;
1844 }
1845 FREE_STRING(ctx->xml_ctx.ctx, value);
1846
Radek Krejcid6b76452019-09-03 17:03:03 +02001847 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001848}
1849
1850/**
1851 * @brief Parse when element.
1852 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001853 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001854 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of when element.
1855 * @param[in,out] data Data to read from, always moved to currently handled character.
1856 * @param[out] when_p When pointer to parse to.
1857 */
1858static LY_ERR
1859yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
1860{
1861 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001862 LY_ERR ret = LY_SUCCESS;
1863
David Sedlákdfbbb442019-08-06 16:33:21 +02001864 when = calloc(1, sizeof *when);
1865 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001866 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 +02001867 LY_CHECK_ERR_RET(ret, free(when), ret);
1868
David Sedlákdfbbb442019-08-06 16:33:21 +02001869 *when_p = when;
1870 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001871 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1872 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1873 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001874 };
1875
Radek Krejcid6b76452019-09-03 17:03:03 +02001876 return yin_parse_content(ctx, subelems, 3, data, LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001877}
1878
1879/**
1880 * @brief Parse yin-elemenet element.
1881 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001882 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001883 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yin-element element.
1884 * @param[in,out] data Data to read from, always moved to currently handled position.
1885 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001886 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001887 *
1888 * @return LY_ERR values.
1889 */
1890static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001891yin_parse_yin_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdfbbb442019-08-06 16:33:21 +02001892 uint16_t *flags, struct lysp_ext_instance **exts)
1893{
1894 const char *temp_val = NULL;
1895 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001896 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001897 };
1898
Radek Krejcid6b76452019-09-03 17:03:03 +02001899 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 +02001900 if (strcmp(temp_val, "true") == 0) {
1901 *flags |= LYS_YINELEM_TRUE;
1902 } else if (strcmp(temp_val, "false") == 0) {
1903 *flags |= LYS_YINELEM_FALSE;
1904 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001905 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1906 "yin-element", "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001907 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1908 return LY_EVALID;
1909 }
1910 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1911
Radek Krejcid6b76452019-09-03 17:03:03 +02001912 return yin_parse_content(ctx, subelems, 1, data, LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001913}
1914
1915/**
1916 * @brief Parse argument element.
1917 *
1918 * @param[in,out] xml_ctx Xml context.
1919 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of argument element.
1920 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001921 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1922 * @param[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_argument(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdfbbb442019-08-06 16:33:21 +02001928 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
1929{
1930 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001931 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1932 {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_NAME, arg_meta->argument, Y_IDENTIF_ARG, LY_STMT_ARGUMENT));
David Sedlákdfbbb442019-08-06 16:33:21 +02001936
Radek Krejcid6b76452019-09-03 17:03:03 +02001937 return yin_parse_content(ctx, subelems, 2, data, LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001938}
1939
1940/**
1941 * @brief Parse the extension statement.
1942 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001943 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001944 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension element.
1945 * @param[in,out] data Data to read from.
1946 * @param[in,out] extensions Extensions to add to.
1947 *
1948 * @return LY_ERR values.
1949 */
1950static LY_ERR
1951yin_parse_extension(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_ext **extensions)
1952{
1953 struct lysp_ext *ex;
1954 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001955 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 +02001956
1957 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1958 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001959 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1960 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1961 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1962 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1963 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001964 };
1965
Radek Krejcid6b76452019-09-03 17:03:03 +02001966 return yin_parse_content(ctx, subelems, 5, data, LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001967}
1968
1969/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001970 * @brief Parse feature element.
1971 *
1972 * @param[in,out] ctx YIN parser context for logging and to store current state.
1973 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1974 * @param[in,out] data Data to read from, always moved to currently handled character.
1975 * @param[in,out] features Features to add to.
1976 *
1977 * @return LY_ERR values.
1978 */
1979static LY_ERR
1980yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1981 struct lysp_feature **features)
1982{
1983 struct lysp_feature *feat;
1984
1985 /* allocate new feature */
1986 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
1987
1988 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02001989 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 +02001990
1991 /* parse content */
1992 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001993 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1994 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
1995 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1996 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1997 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák5e13dea2019-07-22 16:06:45 +02001998 };
Radek Krejcid6b76452019-09-03 17:03:03 +02001999 return yin_parse_content(ctx, subelems, 5, data, LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02002000}
2001
2002/**
David Sedlák28794f22019-07-22 16:45:00 +02002003 * @brief Parse identity element.
2004 *
2005 * @param[in,out] ctx YIN parser context for logging and to store current state.
2006 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2007 * @param[in,out] data Data to read from, always moved to currently handled character.
2008 * @param[in,out] identities Identities to add to.
2009 *
2010 * @return LY_ERR values.
2011 */
2012static LY_ERR
2013yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2014 struct lysp_ident **identities)
2015{
2016 struct lysp_ident *ident;
2017
2018 /* allocate new identity */
2019 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
2020
2021 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002022 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 +02002023
2024 /* parse content */
2025 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002026 {LY_STMT_BASE, &ident->bases, 0},
2027 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2028 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2029 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2030 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2031 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák28794f22019-07-22 16:45:00 +02002032 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002033 return yin_parse_content(ctx, subelems, 6, data, LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002034}
2035
2036/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002037 * @brief Parse list element.
2038 *
2039 * @param[in,out] ctx YIN parser context for logging and to store current state.
2040 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2041 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002042 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002043 *
2044 * @return LY_ERR values.
2045 */
2046static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02002047yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2048 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002049{
David Sedlákaf536aa2019-07-23 13:42:23 +02002050 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002051 LY_ERR ret = LY_SUCCESS;
2052 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02002053
David Sedlákbf8a2b72019-08-14 16:48:10 +02002054 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, list, next);
David Sedlákaf536aa2019-07-23 13:42:23 +02002055 list->nodetype = LYS_LIST;
2056 list->parent = node_meta->parent;
2057
David Sedlákaf536aa2019-07-23 13:42:23 +02002058 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002059 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 +02002060
2061 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02002062 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002063 LY_STMT_ACTION, &list->actions, 0,
2064 LY_STMT_ANYDATA, &list->child, 0,
2065 LY_STMT_ANYXML, &list->child, 0,
2066 LY_STMT_CHOICE, &list->child, 0,
2067 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2068 LY_STMT_CONTAINER, &list->child, 0,
2069 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2070 LY_STMT_GROUPING, &list->groupings, 0,
2071 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2072 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2073 LY_STMT_LEAF, &list->child, 0,
2074 LY_STMT_LEAF_LIST, &list->child, 0,
2075 LY_STMT_LIST, &list->child, 0,
2076 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2077 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2078 LY_STMT_MUST, &list->musts, 0,
2079 LY_STMT_NOTIFICATION, &list->notifs, 0,
2080 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2081 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2082 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2083 LY_STMT_TYPEDEF, &list->typedefs, 0,
2084 LY_STMT_UNIQUE, &list->uniques, 0,
2085 LY_STMT_USES, &list->child, 0,
2086 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2087 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002088 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002089 ret = yin_parse_content(ctx, subelems, 25, data, LY_STMT_LIST, NULL, &list->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002090 subelems_deallocator(25, subelems);
2091 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002092
2093 /* finalize parent pointers to the reallocated items */
2094 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
2095
2096 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02002097 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002098 return LY_EVALID;
2099 }
2100
2101 return LY_SUCCESS;
2102}
2103
2104/**
David Sedlák031b9e72019-07-23 15:19:37 +02002105 * @brief Parse notification element.
2106 *
2107 * @param[in,out] ctx YIN parser context for logging and to store current state.
2108 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2109 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02002110 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002111 *
2112 * @return LY_ERR values.
2113 */
2114static LY_ERR
2115yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002116 struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002117{
2118 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002119 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002120 LY_ERR ret = LY_SUCCESS;
2121 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002122
2123 /* allocate new notification */
David Sedlák6881b512019-08-13 12:52:00 +02002124 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002125 notif->nodetype = LYS_NOTIF;
2126 notif->parent = notif_meta->parent;
2127
2128 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002129 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 +02002130
2131 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002132 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002133 LY_STMT_ANYDATA, &notif->data, 0,
2134 LY_STMT_ANYXML, &notif->data, 0,
2135 LY_STMT_CHOICE, &notif->data, 0,
2136 LY_STMT_CONTAINER, &notif->data, 0,
2137 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2138 LY_STMT_GROUPING, &notif->groupings, 0,
2139 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2140 LY_STMT_LEAF, &notif->data, 0,
2141 LY_STMT_LEAF_LIST, &notif->data, 0,
2142 LY_STMT_LIST, &notif->data, 0,
2143 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2144 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2145 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2146 LY_STMT_TYPEDEF, &notif->typedefs, 0,
2147 LY_STMT_USES, &notif->data, 0,
2148 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002149 ));
2150
Radek Krejcid6b76452019-09-03 17:03:03 +02002151 ret = yin_parse_content(ctx, subelems, 16, data, LY_STMT_NOTIFICATION, NULL, &notif->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002152 subelems_deallocator(16, subelems);
2153 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002154
2155 /* finalize parent pointers to the reallocated items */
2156 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2157
2158 return LY_SUCCESS;
2159}
2160
2161/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002162 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002163 *
2164 * @param[in,out] ctx YIN parser context for logging and to store current state.
2165 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2166 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002167 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002168 *
2169 * @return LY_ERR values.
2170 */
2171static LY_ERR
2172yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002173 struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002174{
2175 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002176 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002177 LY_ERR ret = LY_SUCCESS;
2178 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002179
2180 /* create new grouping */
David Sedlák6881b512019-08-13 12:52:00 +02002181 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002182 grp->nodetype = LYS_GROUPING;
2183 grp->parent = gr_meta->parent;
2184
2185 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002186 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 +02002187
2188 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002189 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002190 LY_STMT_ACTION, &grp->actions, 0,
2191 LY_STMT_ANYDATA, &grp->data, 0,
2192 LY_STMT_ANYXML, &grp->data, 0,
2193 LY_STMT_CHOICE, &grp->data, 0,
2194 LY_STMT_CONTAINER, &grp->data, 0,
2195 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2196 LY_STMT_GROUPING, &grp->groupings, 0,
2197 LY_STMT_LEAF, &grp->data, 0,
2198 LY_STMT_LEAF_LIST, &grp->data, 0,
2199 LY_STMT_LIST, &grp->data, 0,
2200 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2201 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2202 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2203 LY_STMT_TYPEDEF, &grp->typedefs, 0,
2204 LY_STMT_USES, &grp->data, 0,
2205 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002206 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002207 ret = yin_parse_content(ctx, subelems, 16, data, LY_STMT_GROUPING, NULL, &grp->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002208 subelems_deallocator(16, subelems);
2209 LY_CHECK_RET(ret);
2210
David Sedláke3ce9ef2019-07-23 16:34:30 +02002211 /* finalize parent pointers to the reallocated items */
2212 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2213
2214 return LY_SUCCESS;
2215}
2216
2217/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002218 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002219 *
2220 * @param[in,out] ctx YIN parser context for logging and to store current state.
2221 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2222 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002223 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002224 *
2225 * @return LY_ERR values.
2226 */
2227static LY_ERR
2228yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2229 struct tree_node_meta *node_meta)
2230{
David Sedlákf111bcb2019-07-23 17:15:51 +02002231 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002232 LY_ERR ret = LY_SUCCESS;
2233 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002234
2235 /* create new container */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002236 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, cont, next);
David Sedlákf111bcb2019-07-23 17:15:51 +02002237 cont->nodetype = LYS_CONTAINER;
2238 cont->parent = node_meta->parent;
2239
David Sedlákf111bcb2019-07-23 17:15:51 +02002240 /* parse aegument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002241 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 +02002242
2243 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002244 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002245 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2246 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2247 LY_STMT_ANYXML, &cont->child, 0,
2248 LY_STMT_CHOICE, &cont->child, 0,
2249 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2250 LY_STMT_CONTAINER, &cont->child, 0,
2251 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2252 LY_STMT_GROUPING, &cont->groupings, 0,
2253 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2254 LY_STMT_LEAF, &cont->child, 0,
2255 LY_STMT_LEAF_LIST, &cont->child, 0,
2256 LY_STMT_LIST, &cont->child, 0,
2257 LY_STMT_MUST, &cont->musts, 0,
2258 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2259 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2260 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2261 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2262 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2263 LY_STMT_USES, &cont->child, 0,
2264 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2265 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002266 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002267 ret = yin_parse_content(ctx, subelems, 21, data, LY_STMT_CONTAINER, NULL, &cont->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002268 subelems_deallocator(21, subelems);
2269 LY_CHECK_RET(ret);
2270
David Sedlákf111bcb2019-07-23 17:15:51 +02002271 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2272
2273 return LY_SUCCESS;
2274}
2275
2276/**
David Sedlák5379d392019-07-24 10:42:03 +02002277 * @brief Parse case element.
2278 *
2279 * @param[in,out] ctx YIN parser context for logging and to store current state.
2280 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2281 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002282 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002283 *
2284 * @return LY_ERR values.
2285 */
2286static LY_ERR
2287yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2288 struct tree_node_meta *node_meta)
2289{
David Sedlák5379d392019-07-24 10:42:03 +02002290 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002291 LY_ERR ret = LY_SUCCESS;
2292 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002293
2294 /* create new case */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002295 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, cas, next);
David Sedlák5379d392019-07-24 10:42:03 +02002296 cas->nodetype = LYS_CASE;
2297 cas->parent = node_meta->parent;
2298
David Sedlák5379d392019-07-24 10:42:03 +02002299 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002300 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 +02002301
2302 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002303 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002304 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2305 LY_STMT_ANYXML, &cas->child, 0,
2306 LY_STMT_CHOICE, &cas->child, 0,
2307 LY_STMT_CONTAINER, &cas->child, 0,
2308 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2309 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2310 LY_STMT_LEAF, &cas->child, 0,
2311 LY_STMT_LEAF_LIST, &cas->child, 0,
2312 LY_STMT_LIST, &cas->child, 0,
2313 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2314 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2315 LY_STMT_USES, &cas->child, 0,
2316 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2317 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002318 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002319 ret = yin_parse_content(ctx, subelems, 14, data, LY_STMT_CASE, NULL, &cas->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002320 subelems_deallocator(14, subelems);
2321
2322 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002323}
2324
2325/**
David Sedlák05404f62019-07-24 14:11:53 +02002326 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002327 *
2328 * @param[in,out] ctx YIN parser context for logging and to store current state.
2329 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2330 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002331 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002332 *
2333 * @return LY_ERR values.
2334 */
2335LY_ERR
2336yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2337 struct tree_node_meta *node_meta)
2338{
David Sedlák81497a32019-08-13 16:56:26 +02002339 LY_ERR ret = LY_SUCCESS;
2340 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002341 struct lysp_node_choice *choice;
2342
2343 /* create new choice */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002344 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, choice, next);
David Sedlák8d552d62019-08-06 15:29:05 +02002345
David Sedlákb7abcfa2019-07-24 12:33:35 +02002346 choice->nodetype = LYS_CHOICE;
2347 choice->parent = node_meta->parent;
2348
David Sedlákb7abcfa2019-07-24 12:33:35 +02002349 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002350 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 +02002351
2352 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002353 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002354 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2355 LY_STMT_ANYXML, &choice->child, 0,
2356 LY_STMT_CASE, &choice->child, 0,
2357 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2358 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2359 LY_STMT_CONTAINER, &choice->child, 0,
2360 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2361 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2362 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2363 LY_STMT_LEAF, &choice->child, 0,
2364 LY_STMT_LEAF_LIST, &choice->child, 0,
2365 LY_STMT_LIST, &choice->child, 0,
2366 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2367 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2368 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2369 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2370 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002371 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002372 ret = yin_parse_content(ctx, subelems, 17, data, LY_STMT_CHOICE, NULL, &choice->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002373 subelems_deallocator(17, subelems);
2374 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002375}
2376
2377/**
David Sedlák05404f62019-07-24 14:11:53 +02002378 * @brief Parse input or output element.
2379 *
2380 * @param[in,out] ctx YIN parser context for logging and to store current state.
2381 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2382 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002383 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002384 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2385 *
2386 * @return LY_ERR values.
2387 */
2388static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02002389yin_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 +02002390 struct inout_meta *inout_meta)
2391{
David Sedlák81497a32019-08-13 16:56:26 +02002392 LY_ERR ret = LY_SUCCESS;
2393 struct yin_subelement *subelems = NULL;
2394
David Sedlák05404f62019-07-24 14:11:53 +02002395 /* initiate structure */
Radek Krejcid6b76452019-09-03 17:03:03 +02002396 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002397 inout_meta->inout_p->parent = inout_meta->parent;
2398
2399 /* check attributes */
2400 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
2401
2402 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002403 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002404 LY_STMT_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2405 LY_STMT_ANYXML, &inout_meta->inout_p->data, 0,
2406 LY_STMT_CHOICE, &inout_meta->inout_p->data, 0,
2407 LY_STMT_CONTAINER, &inout_meta->inout_p->data, 0,
2408 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2409 LY_STMT_LEAF, &inout_meta->inout_p->data, 0,
2410 LY_STMT_LEAF_LIST, &inout_meta->inout_p->data, 0,
2411 LY_STMT_LIST, &inout_meta->inout_p->data, 0,
2412 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2413 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2414 LY_STMT_USES, &inout_meta->inout_p->data, 0,
2415 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002416 ));
2417 ret = yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts);
2418 subelems_deallocator(12, subelems);
2419 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002420
2421 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002422 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 +02002423
2424 return LY_SUCCESS;
2425}
2426
David Sedlák992fb7c2019-07-24 16:51:01 +02002427/**
2428 * @brief Parse action element.
2429 *
2430 * @param[in,out] ctx YIN parser context for logging and to store current state.
2431 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2432 * @param[in,out] data Data to read from, always moved to currently handled character.
2433 * @param[in] act_meta Meta information about parent node and actions to add to.
2434 *
2435 * @return LY_ERR values.
2436 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002437static LY_ERR
2438yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002439 struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002440{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002441 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002442 LY_ERR ret = LY_SUCCESS;
2443 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002444
2445 /* create new action */
David Sedlák6881b512019-08-13 12:52:00 +02002446 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *acts, act, LY_EMEM);
David Sedlák85d0eca2019-07-24 15:15:21 +02002447 act->nodetype = LYS_ACTION;
2448 act->parent = act_meta->parent;
2449
2450 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002451 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 +02002452
2453 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002454 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002455 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2456 LY_STMT_GROUPING, &act->groupings, 0,
2457 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2458 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2459 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2460 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2461 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2462 LY_STMT_TYPEDEF, &act->typedefs, 0,
2463 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002464 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002465 ret = (yin_parse_content(ctx, subelems, 9, data, LY_STMT_ACTION, NULL, &act->exts));
David Sedlák81497a32019-08-13 16:56:26 +02002466 subelems_deallocator(9, subelems);
2467 LY_CHECK_RET(ret);
2468
David Sedlák85d0eca2019-07-24 15:15:21 +02002469 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2470
2471 return LY_SUCCESS;
2472}
2473
David Sedlák05404f62019-07-24 14:11:53 +02002474/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002475 * @brief Parse augment element.
2476 *
2477 * @param[in,out] ctx YIN parser context for logging and to store current state.
2478 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2479 * @param[in,out] data Data to read from, always moved to currently handled character.
2480 * @param[in] aug_meta Meta information about parent node and augments to add to.
2481 *
2482 * @return LY_ERR values.
2483 */
2484static LY_ERR
2485yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002486 struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002487{
2488 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002489 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002490 LY_ERR ret = LY_SUCCESS;
2491 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002492
2493 /* create new augment */
David Sedlák6881b512019-08-13 12:52:00 +02002494 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002495 aug->nodetype = LYS_AUGMENT;
2496 aug->parent = aug_meta->parent;
2497
2498 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002499 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 +02002500 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2501
2502 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002503 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002504 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2505 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2506 LY_STMT_ANYXML, &aug->child, 0,
2507 LY_STMT_CASE, &aug->child, 0,
2508 LY_STMT_CHOICE, &aug->child, 0,
2509 LY_STMT_CONTAINER, &aug->child, 0,
2510 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2511 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
2512 LY_STMT_LEAF, &aug->child, 0,
2513 LY_STMT_LEAF_LIST, &aug->child, 0,
2514 LY_STMT_LIST, &aug->child, 0,
2515 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2516 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2517 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2518 LY_STMT_USES, &aug->child, 0,
2519 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2520 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002521 ));
Radek Krejcid6b76452019-09-03 17:03:03 +02002522 ret = yin_parse_content(ctx, subelems, 17, data, LY_STMT_AUGMENT, NULL, &aug->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002523 subelems_deallocator(17, subelems);
2524 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002525
2526 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2527
2528 return LY_SUCCESS;
2529}
2530
David Sedlák8b754462019-07-25 16:22:13 +02002531/**
2532 * @brief Parse deviate element.
2533 *
2534 * @param[in,out] ctx YIN parser context for logging and to store current state.
2535 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2536 * @param[in,out] data Data to read from, always moved to currently handled character.
2537 * @param[in] deviates Deviates to add to.
2538 *
2539 * @return LY_ERR values.
2540 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002541static LY_ERR
2542yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2543 struct lysp_deviate **deviates)
2544{
2545 LY_ERR ret = LY_SUCCESS;
2546 uint8_t dev_mod;
2547 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002548 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002549 struct lysp_deviate_add *d_add = NULL;
2550 struct lysp_deviate_rpl *d_rpl = NULL;
2551 struct lysp_deviate_del *d_del = NULL;
2552
2553 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002554 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 +02002555
2556 if (strcmp(temp_val, "not-supported") == 0) {
2557 dev_mod = LYS_DEV_NOT_SUPPORTED;
2558 } else if (strcmp(temp_val, "add") == 0) {
2559 dev_mod = LYS_DEV_ADD;
2560 } else if (strcmp(temp_val, "replace") == 0) {
2561 dev_mod = LYS_DEV_REPLACE;
2562 } else if (strcmp(temp_val, "delete") == 0) {
2563 dev_mod = LYS_DEV_DELETE;
2564 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002565 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
2566 "not-supported", "add", "replace", "delete");
David Sedlák4ffcec82019-07-25 15:10:21 +02002567 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2568 return LY_EVALID;
2569 }
2570 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2571
2572 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2573 d = calloc(1, sizeof *d);
2574 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2575 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002576 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák4ffcec82019-07-25 15:10:21 +02002577 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002578 ret = yin_parse_content(ctx, subelems, 1, data, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002579
2580 } else if (dev_mod == LYS_DEV_ADD) {
2581 d_add = calloc(1, sizeof *d_add);
2582 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2583 d = (struct lysp_deviate *)d_add;
2584 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2585 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2586 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002587 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2588 {LY_STMT_DEFAULT, &d_add->dflts, 0},
2589 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2590 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2591 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2592 {LY_STMT_MUST, &d_add->musts, 0},
2593 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2594 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2595 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002596 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002597 ret = yin_parse_content(ctx, subelems, 9, data, LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002598
2599 } else if (dev_mod == LYS_DEV_REPLACE) {
2600 d_rpl = calloc(1, sizeof *d_rpl);
2601 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2602 d = (struct lysp_deviate *)d_rpl;
2603 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2604 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2605 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002606 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2607 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2608 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2609 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2610 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2611 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2612 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2613 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002614 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002615 ret = yin_parse_content(ctx, subelems, 8, data, LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002616
2617 } else {
2618 d_del = calloc(1, sizeof *d_del);
2619 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2620 d = (struct lysp_deviate *)d_del;
2621 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002622 {LY_STMT_DEFAULT, &d_del->dflts, 0},
2623 {LY_STMT_MUST, &d_del->musts, 0},
2624 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2625 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2626 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002627 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002628 ret = yin_parse_content(ctx, subelems, 5, data, LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002629 }
2630 LY_CHECK_GOTO(ret, cleanup);
2631
2632 d->mod = dev_mod;
2633 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002634 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002635
2636 return ret;
2637
2638cleanup:
2639 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002640 return ret;
2641}
2642
David Sedlák992fb7c2019-07-24 16:51:01 +02002643/**
David Sedlák8b754462019-07-25 16:22:13 +02002644 * @brief Parse deviation element.
2645 *
2646 * @param[in,out] ctx YIN parser context for logging and to store current state.
2647 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2648 * @param[in,out] data Data to read from, always moved to currently handled character.
2649 * @param[in] deviations Deviations to add to.
2650 *
2651 * @return LY_ERR values.
2652 */
2653static LY_ERR
2654yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2655 struct lysp_deviation **deviations)
2656{
2657 struct lysp_deviation *dev;
2658
2659 /* create new deviation */
2660 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2661
2662 /* parse argument */
Radek Krejcid6b76452019-09-03 17:03:03 +02002663 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 +02002664 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2665 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002666 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2667 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2668 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2669 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8b754462019-07-25 16:22:13 +02002670 };
Radek Krejcid6b76452019-09-03 17:03:03 +02002671 return yin_parse_content(ctx, subelems, 4, data, LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002672}
2673
2674/**
David Sedlákb4e44562019-07-04 15:42:12 +02002675 * @brief Map keyword type to substatement info.
2676 *
2677 * @param[in] kw Keyword type.
2678 *
2679 * @return correct LYEXT_SUBSTMT information.
2680 */
2681static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002682kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002683{
2684 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002685 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002686 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002687 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002688 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002689 case LY_STMT_BELONGS_TO:
David Sedlákb4e44562019-07-04 15:42:12 +02002690 return LYEXT_SUBSTMT_BELONGSTO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002691 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002692 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002693 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002694 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002695 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002696 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002697 case LY_STMT_ERROR_APP_TAG:
David Sedlákb4e44562019-07-04 15:42:12 +02002698 return LYEXT_SUBSTMT_ERRTAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002699 case LY_STMT_ERROR_MESSAGE:
David Sedlákb4e44562019-07-04 15:42:12 +02002700 return LYEXT_SUBSTMT_ERRMSG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002701 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002702 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002703 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002704 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002705 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002706 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002707 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002708 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002709 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002710 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002711 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002712 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002713 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002714 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002715 case LY_STMT_REVISION_DATE:
David Sedlákb4e44562019-07-04 15:42:12 +02002716 return LYEXT_SUBSTMT_REVISIONDATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002717 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002718 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002719 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002720 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002721 case LY_STMT_YANG_VERSION:
David Sedlákb4e44562019-07-04 15:42:12 +02002722 return LYEXT_SUBSTMT_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002723 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002724 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002725 case LY_STMT_REQUIRE_INSTANCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002726 return LYEXT_SUBSTMT_REQINSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002727 case LY_STMT_YIN_ELEMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002728 return LYEXT_SUBSTMT_YINELEM;
Radek Krejcid6b76452019-09-03 17:03:03 +02002729 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002730 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002731 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002732 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002733 case LY_STMT_ORDERED_BY:
David Sedlákb4e44562019-07-04 15:42:12 +02002734 return LYEXT_SUBSTMT_ORDEREDBY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002735 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002736 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002737 case LY_STMT_FRACTION_DIGITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002738 return LYEXT_SUBSTMT_FRACDIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002739 case LY_STMT_MAX_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002740 return LYEXT_SUBSTMT_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002741 case LY_STMT_MIN_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002742 return LYEXT_SUBSTMT_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02002743 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002744 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002745 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002746 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002747 case LY_STMT_IF_FEATURE:
David Sedlákb4e44562019-07-04 15:42:12 +02002748 return LYEXT_SUBSTMT_IFFEATURE;
2749 default:
2750 return LYEXT_SUBSTMT_SELF;
2751 }
2752}
2753
David Sedlákc5b20842019-08-13 10:18:31 +02002754/**
2755 * @brief map keyword to keyword-group.
2756 *
2757 * @param[in] ctx YIN parser context used for logging.
2758 * @param[in] kw Keyword that is child of module or submodule.
2759 * @param[out] group Group of keyword.
2760 *
2761 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2762 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002763static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02002764kw2kw_group(struct yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002765{
2766 switch (kw) {
2767 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02002768 case LY_STMT_NONE:
2769 case LY_STMT_NAMESPACE:
2770 case LY_STMT_PREFIX:
2771 case LY_STMT_BELONGS_TO:
2772 case LY_STMT_YANG_VERSION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002773 *group = Y_MOD_MODULE_HEADER;
2774 break;
2775 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02002776 case LY_STMT_INCLUDE:
2777 case LY_STMT_IMPORT:
David Sedláke6cd89e2019-08-07 12:46:02 +02002778 *group = Y_MOD_LINKAGE;
2779 break;
2780 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02002781 case LY_STMT_ORGANIZATION:
2782 case LY_STMT_CONTACT:
2783 case LY_STMT_DESCRIPTION:
2784 case LY_STMT_REFERENCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002785 *group = Y_MOD_META;
2786 break;
2787 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02002788 case LY_STMT_REVISION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002789 *group = Y_MOD_REVISION;
2790 break;
2791 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02002792 case LY_STMT_ANYDATA:
2793 case LY_STMT_ANYXML:
2794 case LY_STMT_AUGMENT:
2795 case LY_STMT_CHOICE:
2796 case LY_STMT_CONTAINER:
2797 case LY_STMT_DEVIATION:
2798 case LY_STMT_EXTENSION:
2799 case LY_STMT_FEATURE:
2800 case LY_STMT_GROUPING:
2801 case LY_STMT_IDENTITY:
2802 case LY_STMT_LEAF:
2803 case LY_STMT_LEAF_LIST:
2804 case LY_STMT_LIST:
2805 case LY_STMT_NOTIFICATION:
2806 case LY_STMT_RPC:
2807 case LY_STMT_TYPEDEF:
2808 case LY_STMT_USES:
2809 case LY_STMT_EXTENSION_INSTANCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002810 *group = Y_MOD_BODY;
2811 break;
2812 default:
2813 LOGINT(ctx->xml_ctx.ctx);
2814 return LY_EINT;
2815 }
2816
2817 return LY_SUCCESS;
2818}
2819
David Sedlákc5b20842019-08-13 10:18:31 +02002820/**
2821 * @brief Check if relative order of two keywords is valid.
2822 *
2823 * @param[in] ctx YIN parser context used for logging.
2824 * @param[in] kw Current keyword.
2825 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002826 * @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 +02002827 * because relative order is required only in module and submodule sub-elements, used for logging.
2828 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002829 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002830 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002831static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02002832yin_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 +02002833{
Radek Krejcid6b76452019-09-03 17:03:03 +02002834 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002835 enum yang_module_stmt gr, next_gr;
2836
2837 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2838 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2839
2840 if (gr > next_gr) {
2841 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2842 return LY_EVALID;
2843 }
2844
2845 return LY_SUCCESS;
2846}
2847
David Sedlákd6e56892019-07-01 15:40:24 +02002848LY_ERR
Radek Krejci12b1c152019-09-05 16:20:48 +02002849yin_parse_content(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
Radek Krejcid6b76452019-09-03 17:03:03 +02002850 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 +02002851{
2852 LY_ERR ret = LY_SUCCESS;
David Sedlák8e7bda82019-07-16 17:57:50 +02002853 char *out = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +02002854 const char *prefix, *name;
2855 size_t out_len = 0, prefix_len, name_len;
David Sedlák8e7bda82019-07-16 17:57:50 +02002856 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002857 struct yin_arg_record *attrs = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +02002858 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002859 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002860
David Sedlákda8ffa32019-07-08 14:17:10 +02002861 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2862 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002863 /* current element has subelements as content */
2864 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002865 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákc5b20842019-08-13 10:18:31 +02002866 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákd6e56892019-07-01 15:40:24 +02002867 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +02002868 if (!name) {
David Sedlákd6e56892019-07-01 15:40:24 +02002869 /* end of current element reached */
2870 break;
2871 }
David Sedlák1af868e2019-07-17 17:03:14 +02002872 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002873 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6cd89e2019-08-07 12:46:02 +02002874 last_kw = kw;
David Sedlákc5b20842019-08-13 10:18:31 +02002875 kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002876
2877 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002878 subelem = get_record(kw, subelem_info_size, subelem_info);
2879 if (!subelem) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002880 if (current_element == LY_STMT_DEVIATE && isdevsub(kw)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002881 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2882 } else {
David Sedlákc5b20842019-08-13 10:18:31 +02002883 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 +02002884 }
David Sedlákd6e56892019-07-01 15:40:24 +02002885 ret = LY_EVALID;
2886 goto cleanup;
2887 }
2888
David Sedlák6542aed2019-08-14 10:47:43 +02002889 /* relative order is required only in module and submodule sub-elements */
Radek Krejcid6b76452019-09-03 17:03:03 +02002890 if (current_element == LY_STMT_MODULE || current_element == LY_STMT_SUBMODULE) {
David Sedláke6cd89e2019-08-07 12:46:02 +02002891 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2892 LY_CHECK_GOTO(ret, cleanup);
2893 }
David Sedlák5f8191e2019-07-08 16:35:52 +02002894
David Sedlák4ffcec82019-07-25 15:10:21 +02002895 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002896 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002897 /* subelement uniquenes */
David Sedlák1538a842019-08-08 15:38:51 +02002898 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 +02002899 return LY_EVALID;
2900 }
David Sedlák1af868e2019-07-17 17:03:14 +02002901 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002902 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002903 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002904 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002905 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002906 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002907 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002908 if (ctx->mod_version < 2) {
David Sedlák1538a842019-08-08 15:38:51 +02002909 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 +02002910 ret = LY_EVALID;
2911 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002912 }
2913 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002914 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002915 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002916
David Sedlákd6e56892019-07-01 15:40:24 +02002917 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002918 /* call responsible function */
Radek Krejcid6b76452019-09-03 17:03:03 +02002919 case LY_STMT_EXTENSION_INSTANCE:
David Sedláka82ecff2019-08-16 10:51:48 +02002920 ret = yin_parse_extension_instance(ctx, attrs, data, name2fname(name, prefix_len),
2921 len2flen(name_len, prefix_len),
David Sedlák1af868e2019-07-17 17:03:14 +02002922 kw2lyext_substmt(current_element),
2923 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002924 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002925 case LY_STMT_ACTION:
2926 case LY_STMT_RPC:
David Sedlák6881b512019-08-13 12:52:00 +02002927 ret = yin_parse_action(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002928 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002929 case LY_STMT_ANYDATA:
2930 case LY_STMT_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002931 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002932 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002933 case LY_STMT_ARGUMENT:
David Sedlákdf2691f2019-08-15 13:32:27 +02002934 ret = yin_parse_argument(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002935 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002936 case LY_STMT_AUGMENT:
David Sedlák6881b512019-08-13 12:52:00 +02002937 ret = yin_parse_augment(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002938 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002939 case LY_STMT_BASE:
David Sedlák6542aed2019-08-14 10:47:43 +02002940 ret = yin_parse_base(ctx, attrs, data, current_element, subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002941 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002942 case LY_STMT_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002943 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002944 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002945 case LY_STMT_BIT:
David Sedlák43801c92019-08-05 15:58:54 +02002946 ret = yin_parse_bit(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002947 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002948 case LY_STMT_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002949 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002950 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002951 case LY_STMT_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002952 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002953 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002954 case LY_STMT_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02002955 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002956 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002957 case LY_STMT_CONTACT:
2958 case LY_STMT_DESCRIPTION:
2959 case LY_STMT_ORGANIZATION:
2960 case LY_STMT_REFERENCE:
David Sedlákdf2691f2019-08-15 13:32:27 +02002961 ret = yin_parse_meta(ctx, attrs, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002962 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002963 case LY_STMT_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02002964 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002965 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002966 case LY_STMT_DEFAULT:
2967 case LY_STMT_ERROR_APP_TAG:
2968 case LY_STMT_KEY:
2969 case LY_STMT_PRESENCE:
David Sedlák6542aed2019-08-14 10:47:43 +02002970 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 +02002971 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002972 case LY_STMT_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002973 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002974 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002975 case LY_STMT_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02002976 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002977 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002978 case LY_STMT_ENUM:
David Sedlák43801c92019-08-05 15:58:54 +02002979 ret = yin_parse_enum(ctx, attrs, data, (struct lysp_type *)subelem->dest);
2980 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002981 case LY_STMT_ERROR_MESSAGE:
David Sedlákdf2691f2019-08-15 13:32:27 +02002982 ret = yin_parse_err_msg(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002983 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002984 case LY_STMT_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002985 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002986 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002987 case LY_STMT_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02002988 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002989 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002990 case LY_STMT_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002991 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002992 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002993 case LY_STMT_GROUPING:
David Sedlák6881b512019-08-13 12:52:00 +02002994 ret = yin_parse_grouping(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002995 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002996 case LY_STMT_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02002997 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002998 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002999 case LY_STMT_IF_FEATURE:
3000 case LY_STMT_UNITS:
David Sedlák6542aed2019-08-14 10:47:43 +02003001 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 +02003002 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003003 case LY_STMT_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02003004 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003005 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003006 case LY_STMT_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02003007 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003008 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003009 case LY_STMT_INPUT:
3010 case LY_STMT_OUTPUT:
David Sedlák05404f62019-07-24 14:11:53 +02003011 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003012 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003013 case LY_STMT_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02003014 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003015 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003016 case LY_STMT_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02003017 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003018 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003019 case LY_STMT_LENGTH:
David Sedlák6542aed2019-08-14 10:47:43 +02003020 ret = yin_parse_length(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003021 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003022 case LY_STMT_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02003023 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003024 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003025 case LY_STMT_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02003026 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003027 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003028 case LY_STMT_MAX_ELEMENTS:
3029 case LY_STMT_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02003030 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003031 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003032 case LY_STMT_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02003033 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003034 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003035 case LY_STMT_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02003036 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003037 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003038 case LY_STMT_NAMESPACE:
David Sedlák6542aed2019-08-14 10:47:43 +02003039 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 +02003040 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003041 case LY_STMT_NOTIFICATION:
David Sedlák6881b512019-08-13 12:52:00 +02003042 ret = yin_parse_notification(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003043 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003044 case LY_STMT_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02003045 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003046 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003047 case LY_STMT_PATH:
David Sedlák6542aed2019-08-14 10:47:43 +02003048 ret = yin_parse_path(ctx, attrs, data, kw, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003049 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003050 case LY_STMT_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02003051 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003052 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003053 case LY_STMT_VALUE:
3054 case LY_STMT_POSITION:
David Sedlákdf2691f2019-08-15 13:32:27 +02003055 ret = yin_parse_value_pos(ctx, attrs, data, kw, (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003056 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003057 case LY_STMT_PREFIX:
David Sedlák6542aed2019-08-14 10:47:43 +02003058 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 +02003059 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003060 case LY_STMT_RANGE:
David Sedlák6542aed2019-08-14 10:47:43 +02003061 ret = yin_parse_range(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003062 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003063 case LY_STMT_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02003064 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003065 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003066 case LY_STMT_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02003067 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003068 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003069 case LY_STMT_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02003070 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003071 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003072 case LY_STMT_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02003073 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003074 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003075 case LY_STMT_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02003076 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003077 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003078 case LY_STMT_TYPE:
David Sedlák6542aed2019-08-14 10:47:43 +02003079 ret = yin_parse_type(ctx, attrs, data, current_element, subelem);
David Sedlákd6e56892019-07-01 15:40:24 +02003080 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003081 case LY_STMT_TYPEDEF:
David Sedlák6881b512019-08-13 12:52:00 +02003082 ret = yin_parse_typedef(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003083 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003084 case LY_STMT_UNIQUE:
David Sedlák6542aed2019-08-14 10:47:43 +02003085 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 +02003086 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003087 case LY_STMT_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02003088 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003089 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003090 case LY_STMT_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02003091 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003092 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003093 case LY_STMT_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003094 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003095 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003096 case LY_STMT_YIN_ELEMENT:
David Sedlákdf2691f2019-08-15 13:32:27 +02003097 ret = yin_parse_yin_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02003098 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003099 case LY_STMT_ARG_TEXT:
3100 case LY_STMT_ARG_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02003101 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02003102 break;
3103 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02003104 LOGINT(ctx->xml_ctx.ctx);
David Sedlákbf8a2b72019-08-14 16:48:10 +02003105 ret = LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02003106 }
David Sedlák3ffbc522019-07-02 17:49:28 +02003107 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02003108 FREE_ARRAY(ctx, attrs, free_arg_rec);
3109 attrs = NULL;
3110 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02003111 }
3112 } else {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003113 LY_CHECK_RET(ret);
David Sedlákd6e56892019-07-01 15:40:24 +02003114 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02003115 /* save text content, if text_content isn't set, it's just ignored */
David Sedlákc5b20842019-08-13 10:18:31 +02003116 /* no resources are allocated in this branch, no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02003117 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02003118 if (text_content) {
David Sedlák169cc522019-08-15 13:23:45 +02003119 INSERT_STRING(ctx->xml_ctx.ctx, *text_content, dynamic, out, out_len);
3120 LY_CHECK_RET(!*text_content, LY_EMEM);
David Sedlák3ffbc522019-07-02 17:49:28 +02003121 }
David Sedlákd6e56892019-07-01 15:40:24 +02003122 /* load closing element */
David Sedlákc5b20842019-08-13 10:18:31 +02003123 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákd6e56892019-07-01 15:40:24 +02003124 }
3125 }
David Sedlák8b754462019-07-25 16:22:13 +02003126 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3127 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003128
3129cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02003130 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02003131 return ret;
3132}
3133
David Sedlák619db942019-07-03 14:47:30 +02003134LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02003135yin_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 +02003136 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003137{
3138 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003139 char *out;
3140 const char *name, *prefix;
3141 size_t out_len, prefix_len, name_len;
3142 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003143 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003144 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
3145 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003146
David Sedlákda8ffa32019-07-08 14:17:10 +02003147 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003148
3149 e->yin = 0;
3150 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02003151 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02003152 e->insubstmt = subelem;
3153 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003154 e->yin |= LYS_YIN;
3155
David Sedlákb1a78352019-06-28 16:16:29 +02003156 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02003157 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02003158 if (!iter->prefix) {
3159 new_subelem = calloc(1, sizeof(*new_subelem));
3160 if (!e->child) {
3161 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003162 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003163 last_subelem->next = new_subelem;
3164 }
3165 last_subelem = new_subelem;
3166
3167 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003168 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
David Sedlák169cc522019-08-15 13:23:45 +02003169 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3170
3171 INSERT_STRING(ctx->xml_ctx.ctx, last_subelem->arg, iter->dynamic_content, iter->content, iter->content_len);
3172 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003173 }
3174 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003175
David Sedlákf250ecf2019-07-01 11:02:05 +02003176 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003177 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3178 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003179 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003180 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3181 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02003182 if (!name) {
3183 /* end of extension instance reached */
3184 break;
3185 }
Radek Krejci6df08da2019-09-09 14:07:21 +02003186 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, prefix, prefix_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02003187 if (!e->child) {
3188 e->child = new_subelem;
3189 } else {
3190 last_subelem->next = new_subelem;
3191 }
3192 last_subelem = new_subelem;
3193 }
David Sedlák555c7202019-07-04 12:14:12 +02003194 } else {
David Sedlák169cc522019-08-15 13:23:45 +02003195 if (out_len != 0) {
3196 /* save text content */
3197 LY_CHECK_RET(ret);
3198
3199 INSERT_STRING(ctx->xml_ctx.ctx, e->argument, dynamic, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02003200 LY_CHECK_RET(!e->argument, LY_EMEM);
David Sedlák169cc522019-08-15 13:23:45 +02003201
3202 /* load closing element */
3203 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
3204 LY_CHECK_RET(name, LY_EINT);
David Sedlák555c7202019-07-04 12:14:12 +02003205 }
David Sedlákb1a78352019-06-28 16:16:29 +02003206 }
David Sedlákb1a78352019-06-28 16:16:29 +02003207 }
3208
3209 return LY_SUCCESS;
3210}
3211
3212LY_ERR
David Sedláke6284fc2019-09-10 11:57:02 +02003213yin_parse_arg_inext_known(struct yin_parser_ctx *ctx, const char **data, enum ly_stmt elem_type, struct lysp_stmt **args)
3214{
3215 struct yin_arg_record *attrs;
3216 LY_ERR ret = LY_SUCCESS;
3217 struct lysp_stmt *arg;
3218
3219 ret = yin_load_attributes(ctx, data, &attrs);
3220 LY_CHECK_GOTO(ret, cleanup);
3221
3222 LY_LIST_NEW_GOTO(ctx->xml_ctx.ctx, args, arg, next, ret, cleanup);
3223
3224 switch (elem_type) {
3225 case LY_STMT_ACTION:
3226 case LY_STMT_ANYDATA:
3227 case LY_STMT_ANYXML:
3228 case LY_STMT_ARGUMENT:
3229 case LY_STMT_BASE:
3230 case LY_STMT_BIT:
3231 case LY_STMT_CASE:
3232 case LY_STMT_CHOICE:
3233 case LY_STMT_CONTAINER:
3234 case LY_STMT_ENUM:
3235 case LY_STMT_EXTENSION:
3236 case LY_STMT_FEATURE:
3237 case LY_STMT_GROUPING:
3238 case LY_STMT_IDENTITY:
3239 case LY_STMT_IF_FEATURE:
3240 case LY_STMT_LEAF:
3241 case LY_STMT_LEAF_LIST:
3242 case LY_STMT_LIST:
3243 case LY_STMT_MODULE:
3244 case LY_STMT_NOTIFICATION:
3245 case LY_STMT_RPC:
3246 case LY_STMT_SUBMODULE:
3247 case LY_STMT_TYPE:
3248 case LY_STMT_TYPEDEF:
3249 case LY_STMT_UNITS:
3250 case LY_STMT_USES:
3251 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
3252 break;
3253 case LY_STMT_AUGMENT:
3254 case LY_STMT_DEVIATION:
3255 case LY_STMT_REFINE:
3256 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
3257 break;
3258 case LY_STMT_CONFIG:
3259 case LY_STMT_DEFAULT:
3260 case LY_STMT_DEVIATE:
3261 case LY_STMT_ERROR_APP_TAG:
3262 case LY_STMT_ERROR_MESSAGE:
3263 case LY_STMT_FRACTION_DIGITS:
3264 case LY_STMT_KEY:
3265 case LY_STMT_LENGTH:
3266 case LY_STMT_MANDATORY:
3267 case LY_STMT_MAX_ELEMENTS:
3268 case LY_STMT_MIN_ELEMENTS:
3269 case LY_STMT_MODIFIER:
3270 case LY_STMT_ORDERED_BY:
3271 case LY_STMT_PATH:
3272 case LY_STMT_PATTERN:
3273 case LY_STMT_POSITION:
3274 case LY_STMT_PREFIX:
3275 case LY_STMT_PRESENCE:
3276 case LY_STMT_RANGE:
3277 case LY_STMT_REQUIRE_INSTANCE:
3278 case LY_STMT_STATUS:
3279 case LY_STMT_VALUE:
3280 case LY_STMT_YANG_VERSION:
3281 case LY_STMT_YIN_ELEMENT:
3282 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
3283 break;
3284 case LY_STMT_CONTACT:
3285 case LY_STMT_DESCRIPTION:
3286 case LY_STMT_ORGANIZATION:
3287 case LY_STMT_REFERENCE:
3288 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_TEXT, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
3289 break;
3290 case LY_STMT_IMPORT:
3291 case LY_STMT_INCLUDE:
3292 case LY_STMT_BELONGS_TO:
3293 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
3294 break;
3295 case LY_STMT_INPUT:
3296 case LY_STMT_OUTPUT:
3297 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
3298 break;
3299 case LY_STMT_MUST:
3300 case LY_STMT_WHEN:
3301 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
3302 break;
3303 case LY_STMT_NAMESPACE:
3304 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_URI, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
3305 break;
3306 case LY_STMT_REVISION:
3307 case LY_STMT_REVISION_DATE:
3308 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
3309 break;
3310 case LY_STMT_UNIQUE:
3311 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_TAG, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
3312 break;
3313 default:
3314 LOGINT(ctx->xml_ctx.ctx);
3315 ret = LY_EINT;
3316 }
3317
3318cleanup:
3319 FREE_ARRAY(ctx, attrs, free_arg_rec);
3320 return ret;
3321}
3322
3323LY_ERR
Radek Krejci6df08da2019-09-09 14:07:21 +02003324yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, const char **data,
David Sedlák4ffcec82019-07-25 15:10:21 +02003325 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02003326{
3327 LY_ERR ret = LY_SUCCESS;
3328 const char *temp_prefix, *temp_name;
3329 char *out = NULL;
Radek Krejci6df08da2019-09-09 14:07:21 +02003330 size_t out_len, temp_name_len, temp_prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02003331 int dynamic;
David Sedlákb1a78352019-06-28 16:16:29 +02003332 struct lysp_stmt *last = NULL, *new = NULL;
3333
3334 /* allocate new structure for element */
3335 *element = calloc(1, sizeof(**element));
David Sedlákc005d892019-08-16 09:27:01 +02003336 LY_CHECK_ERR_RET(!(*element), LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
Radek Krejci994fc342019-09-09 14:20:49 +02003337 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, prefix ? prefix : name, prefix_len ? prefix_len + name_len + 1 : name_len);
David Sedlákc005d892019-08-16 09:27:01 +02003338 LY_CHECK_RET(!(*element)->stmt, LY_EMEM);
Radek Krejci6df08da2019-09-09 14:07:21 +02003339 /* TODO map prefix to module name */
3340 (*element)->kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, LY_STMT_EXTENSION_INSTANCE);
David Sedlákb1a78352019-06-28 16:16:29 +02003341
3342 last = (*element)->child;
David Sedláke6284fc2019-09-10 11:57:02 +02003343 if ((*element)->kw == LY_STMT_NONE) {
3344 /* unrecognized element */
3345 /* TODO set parrent correctly */
3346 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(LY_STMT_EXTENSION_INSTANCE));
3347 return LY_EVALID;
3348 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3349 /* element is known yang keyword, which means argument can be parsed correctly. */
3350 LY_CHECK_RET(yin_parse_arg_inext_known(ctx, data, (*element)->kw, &(*element)->child));
3351 } else {
3352 /* load attributes in generic way- TODO in case of non-extension keyword, the argument details are known,
3353 * so the argument can be stored correctly instead of storing pure attributes */
3354 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
3355 /* add new element to linked-list */
3356 new = calloc(1, sizeof(*last));
3357 LY_CHECK_ERR_RET(!new, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
3358 if (!(*element)->child) {
3359 /* save first */
3360 (*element)->child = new;
3361 } else {
3362 last->next = new;
3363 }
3364 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003365
David Sedláke6284fc2019-09-10 11:57:02 +02003366 last->flags |= LYS_YIN_ATTR;
3367 LY_CHECK_RET(lyxml_get_attribute(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len));
3368 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
3369 LY_CHECK_RET(!last->stmt, LY_EMEM);
3370 last->kw = yin_match_keyword(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, LY_STMT_EXTENSION_INSTANCE);
David Sedláka82ecff2019-08-16 10:51:48 +02003371
David Sedláke6284fc2019-09-10 11:57:02 +02003372 LY_CHECK_RET(lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic));
3373 /* attributes with prefix are ignored */
3374 if (!temp_prefix) {
3375 INSERT_STRING(ctx->xml_ctx.ctx, last->arg, dynamic, out, out_len);
3376 LY_CHECK_RET(!last->arg, LY_EMEM);
3377 } else {
3378 if (dynamic) {
3379 free(out);
3380 }
David Sedláka82ecff2019-08-16 10:51:48 +02003381 }
David Sedlákb1a78352019-06-28 16:16:29 +02003382 }
3383 }
3384
David Sedláke6284fc2019-09-10 11:57:02 +02003385
David Sedláka82ecff2019-08-16 10:51:48 +02003386 /* parse content of element if any */
3387 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3388 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
3389 if (ret == LY_EINVAL) {
3390 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3391 /* parse subelements */
3392 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len));
3393 if (!temp_name) {
3394 /* end of element reached */
3395 break;
3396 }
Radek Krejci6df08da2019-09-09 14:07:21 +02003397 LY_CHECK_RET(yin_parse_element_generic(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, data, &new));
David Sedláka82ecff2019-08-16 10:51:48 +02003398 if (!(*element)->child) {
3399 /* save first */
3400 (*element)->child = new;
3401 } else {
3402 last->next = new;
3403 }
3404 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003405 }
David Sedláka82ecff2019-08-16 10:51:48 +02003406 } else {
3407 LY_CHECK_RET(ret);
3408 /* save element content */
3409 if (out_len != 0) {
3410 INSERT_STRING(ctx->xml_ctx.ctx, (*element)->arg, dynamic, out, out_len);
3411 LY_CHECK_RET(!(*element)->arg, LY_EMEM);
3412 }
David Sedlák169cc522019-08-15 13:23:45 +02003413
David Sedláka82ecff2019-08-16 10:51:48 +02003414 /* read closing tag */
Radek Krejci6df08da2019-09-09 14:07:21 +02003415 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len));
David Sedláka82ecff2019-08-16 10:51:48 +02003416 }
David Sedlákb1a78352019-06-28 16:16:29 +02003417 }
3418
David Sedlákc005d892019-08-16 09:27:01 +02003419 return LY_SUCCESS;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003420}
3421
3422LY_ERR
David Sedlák4f03b932019-07-26 13:01:47 +02003423yin_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 +02003424{
David Sedlák81497a32019-08-13 16:56:26 +02003425 LY_ERR ret = LY_SUCCESS;
3426 struct yin_subelement *subelems = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003427
Radek Krejcid6b76452019-09-03 17:03:03 +02003428 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 +02003429 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003430 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3431 LY_STMT_ANYXML, &mod->data, 0,
3432 LY_STMT_AUGMENT, &mod->augments, 0,
3433 LY_STMT_CHOICE, &mod->data, 0,
3434 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3435 LY_STMT_CONTAINER, &mod->data, 0,
3436 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3437 LY_STMT_DEVIATION, &mod->deviations, 0,
3438 LY_STMT_EXTENSION, &mod->extensions, 0,
3439 LY_STMT_FEATURE, &mod->features, 0,
3440 LY_STMT_GROUPING, &mod->groupings, 0,
3441 LY_STMT_IDENTITY, &mod->identities, 0,
3442 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3443 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3444 LY_STMT_LEAF, &mod->data, 0,
3445 LY_STMT_LEAF_LIST, &mod->data, 0,
3446 LY_STMT_LIST, &mod->data, 0,
3447 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3448 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3449 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3450 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3451 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3452 LY_STMT_REVISION, &mod->revs, 0,
3453 LY_STMT_RPC, &mod->rpcs, 0,
3454 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3455 LY_STMT_USES, &mod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003456 LY_STMT_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003457 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003458 ));
3459
Radek Krejcid6b76452019-09-03 17:03:03 +02003460 ret = yin_parse_content(ctx, subelems, 28, data, LY_STMT_MODULE, NULL, &mod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003461 subelems_deallocator(28, subelems);
3462
3463 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003464}
3465
3466LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003467yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3468{
David Sedlák81497a32019-08-13 16:56:26 +02003469 LY_ERR ret = LY_SUCCESS;
3470 struct yin_subelement *subelems = NULL;
David Sedlák298ff6d2019-07-26 14:29:03 +02003471
Radek Krejcid6b76452019-09-03 17:03:03 +02003472 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 +02003473 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003474 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3475 LY_STMT_ANYXML, &submod->data, 0,
3476 LY_STMT_AUGMENT, &submod->augments, 0,
3477 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3478 LY_STMT_CHOICE, &submod->data, 0,
3479 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3480 LY_STMT_CONTAINER, &submod->data, 0,
3481 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3482 LY_STMT_DEVIATION, &submod->deviations, 0,
3483 LY_STMT_EXTENSION, &submod->extensions, 0,
3484 LY_STMT_FEATURE, &submod->features, 0,
3485 LY_STMT_GROUPING, &submod->groupings, 0,
3486 LY_STMT_IDENTITY, &submod->identities, 0,
3487 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3488 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3489 LY_STMT_LEAF, &submod->data, 0,
3490 LY_STMT_LEAF_LIST, &submod->data, 0,
3491 LY_STMT_LIST, &submod->data, 0,
3492 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3493 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3494 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3495 LY_STMT_REVISION, &submod->revs, 0,
3496 LY_STMT_RPC, &submod->rpcs, 0,
3497 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3498 LY_STMT_USES, &submod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003499 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003500 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003501 ));
3502
Radek Krejcid6b76452019-09-03 17:03:03 +02003503 ret = yin_parse_content(ctx, subelems, 27, data, LY_STMT_SUBMODULE, NULL, &submod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003504 subelems_deallocator(27, subelems);
3505
3506 return ret;
David Sedlák298ff6d2019-07-26 14:29:03 +02003507}
3508
3509LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02003510yin_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 +02003511{
Radek Krejcid6b76452019-09-03 17:03:03 +02003512 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003513 LY_ERR ret = LY_SUCCESS;
3514 const char *prefix, *name;
3515 size_t prefix_len, name_len;
3516 struct yin_arg_record *attrs = NULL;
3517 struct lysp_submodule *mod_p = NULL;
3518
3519 /* create context */
3520 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003521 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003522 (*yin_ctx)->xml_ctx.ctx = ctx;
Radek Krejci12b1c152019-09-05 16:20:48 +02003523 (*yin_ctx)->pos_type = LY_VLOG_LINE;
David Sedlák8985a142019-07-31 16:43:06 +02003524 (*yin_ctx)->xml_ctx.line = 1;
3525
David Sedlák1b623122019-08-05 15:27:49 +02003526 /* map the typedefs and groupings list from main context to the submodule's context */
3527 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3528 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3529
David Sedlák8985a142019-07-31 16:43:06 +02003530 /* check submodule */
3531 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3532 LY_CHECK_GOTO(ret, cleanup);
3533 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3534 LY_CHECK_GOTO(ret, cleanup);
Radek Krejcid6b76452019-09-03 17:03:03 +02003535 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, LY_STMT_NONE);
David Sedlák8985a142019-07-31 16:43:06 +02003536
Radek Krejcid6b76452019-09-03 17:03:03 +02003537 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003538 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3539 ret = LY_EINVAL;
3540 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003541 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003542 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003543 ret = LY_EVALID;
3544 goto cleanup;
3545 }
3546
3547 mod_p = calloc(1, sizeof *mod_p);
3548 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3549 mod_p->parsing = 1;
3550
3551 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3552 LY_CHECK_GOTO(ret, cleanup);
3553
David Sedlák6d781b62019-08-02 15:22:52 +02003554 name = NULL;
David Sedlákbf8a2b72019-08-14 16:48:10 +02003555 /* skip possible trailing whitespaces at end of the input */
3556 while(*data && isspace(*data)) {
3557 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003558 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003559 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003560 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 +02003561 ret = LY_EVALID;
3562 goto cleanup;
3563 }
3564
David Sedlák8985a142019-07-31 16:43:06 +02003565 mod_p->parsing = 0;
3566 *submod = mod_p;
3567
3568cleanup:
3569 if (ret) {
3570 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003571 yin_parser_ctx_free(*yin_ctx);
3572 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003573 }
3574
3575 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3576 return ret;
3577}
3578
3579LY_ERR
3580yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003581{
David Sedláke4889912018-11-02 09:52:40 +01003582 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003583 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003584 struct lysp_module *mod_p = NULL;
3585 const char *prefix, *name;
3586 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003587 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003588
David Sedlák8985a142019-07-31 16:43:06 +02003589 /* create context */
3590 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003591 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003592 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
Radek Krejci335332a2019-09-05 13:03:35 +02003593 (*yin_ctx)->pos_type = LY_VLOG_LINE;
David Sedlák8985a142019-07-31 16:43:06 +02003594 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003595
David Sedlák8985a142019-07-31 16:43:06 +02003596 /* check module */
3597 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003598 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003599 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003600 LY_CHECK_GOTO(ret, cleanup);
Radek Krejcid6b76452019-09-03 17:03:03 +02003601 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, LY_STMT_NONE);
3602 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003603 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 +01003604 ret = LY_EINVAL;
3605 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003606 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003607 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003608 ret = LY_EVALID;
3609 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003610 }
3611
David Sedlák3017da42019-02-15 09:48:04 +01003612 /* allocate module */
3613 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003614 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003615 mod_p->mod = mod;
3616 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003617
David Sedlák00250342019-06-21 14:19:39 +02003618 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003619 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003620 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003621
David Sedlákbf8a2b72019-08-14 16:48:10 +02003622 name = NULL;
3623 /* skip possible trailing whitespaces at end of the input */
3624 while(*data && isspace(*data)) {
3625 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003626 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003627 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003628 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 +02003629 ret = LY_EVALID;
3630 goto cleanup;
3631 }
3632
David Sedlák3017da42019-02-15 09:48:04 +01003633 mod_p->parsing = 0;
3634 mod->parsed = mod_p;
3635
3636cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003637 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003638 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003639 yin_parser_ctx_free(*yin_ctx);
3640 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003641 }
David Sedlák8985a142019-07-31 16:43:06 +02003642 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003643 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003644}