blob: 6623820b81172f0c393fd43b45021c4063df6fe0 [file] [log] [blame]
David Sedlákf824ad52018-10-14 23:58:15 +02001/**
2 * @file parser_yin.c
3 * @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
David Sedlák3b4db242018-10-19 16:11:01 +02004 * @brief YIN parser.
5 *
David Sedlákb1ce3f82019-06-05 14:37:26 +02006 * Copyright (c) 2015 - 2019 CESNET, z.s.p.o.
David Sedlák3b4db242018-10-19 16:11:01 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
David Sedlákf824ad52018-10-14 23:58:15 +020013 */
David Sedlákecf5eb82019-06-03 14:12:44 +020014#include "common.h"
15
David Sedlák3ffbc522019-07-02 17:49:28 +020016#include <assert.h>
David Sedlák3b4db242018-10-19 16:11:01 +020017#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
David Sedlák872c7b42018-10-26 13:15:20 +020020#include <string.h>
David Sedlákd6e56892019-07-01 15:40:24 +020021#include <stdbool.h>
David Sedlák5545f5d2019-07-11 11:55:16 +020022#include <errno.h>
David Sedlákf75d55e2019-07-12 16:52:50 +020023#include <ctype.h>
David Sedlák81497a32019-08-13 16:56:26 +020024#include <stdarg.h>
David Sedlákf824ad52018-10-14 23:58:15 +020025
David Sedlákf824ad52018-10-14 23:58:15 +020026#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020027#include "dict.h"
David Sedlák3b4db242018-10-19 16:11:01 +020028#include "xml.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020029#include "tree.h"
30#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020031#include "tree_schema_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020032#include "parser_yin.h"
David Sedlák00250342019-06-21 14:19:39 +020033
David Sedlák2b214ac2019-06-06 16:11:03 +020034/**
35 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020036 *
David Sedlák2b214ac2019-06-06 16:11:03 +020037 * @param ns Namespace URI to check.
38 *
39 * @return true if ns equals YIN_NS_URI false otherwise.
40 */
41#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
42
David Sedlákf6251182019-06-06 10:22:13 +020043const char *const yin_attr_list[] = {
44 [YIN_ARG_NAME] = "name",
45 [YIN_ARG_TARGET_NODE] = "target-node",
46 [YIN_ARG_MODULE] = "module",
47 [YIN_ARG_VALUE] = "value",
48 [YIN_ARG_TEXT] = "text",
49 [YIN_ARG_CONDITION] = "condition",
50 [YIN_ARG_URI] = "uri",
51 [YIN_ARG_DATE] = "date",
52 [YIN_ARG_TAG] = "tag",
David Sedlákf6251182019-06-06 10:22:13 +020053};
54
David Sedlák1bccdfa2019-06-17 15:55:27 +020055enum yang_keyword
David Sedlákc1771b12019-07-10 15:55:46 +020056yin_match_keyword(struct yin_parser_ctx *ctx, const char *name, size_t name_len,
57 const char *prefix, size_t prefix_len, enum yang_keyword parrent)
David Sedlák1bccdfa2019-06-17 15:55:27 +020058{
David Sedlák8f7a1172019-06-20 14:42:18 +020059 const char *start = NULL;
60 enum yang_keyword kw = YANG_NONE;
61 const struct lyxml_ns *ns = NULL;
62
63 if (!name || name_len == 0) {
David Sedlák1bccdfa2019-06-17 15:55:27 +020064 return YANG_NONE;
65 }
66
David Sedlákda8ffa32019-07-08 14:17:10 +020067 ns = lyxml_ns_get(&ctx->xml_ctx, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +020068 if (ns) {
69 if (!IS_YIN_NS(ns->uri)) {
70 return YANG_CUSTOM;
71 }
72 } else {
73 /* elements without namespace are automatically unknown */
74 return YANG_NONE;
75 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020076
David Sedlák8f7a1172019-06-20 14:42:18 +020077 start = name;
78 kw = lysp_match_kw(NULL, &name);
79
80 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +020081 /* this is done because of collision in yang statement value and yang argument mapped to yin element value */
82 if (kw == YANG_VALUE && parrent == YANG_ERROR_MESSAGE) {
83 return YIN_VALUE;
84 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020085 return kw;
86 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020087 if (strncmp(start, "text", name_len) == 0) {
88 return YIN_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +020089 } else {
90 return YANG_NONE;
91 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020092 }
93}
94
David Sedlákc5b20842019-08-13 10:18:31 +020095enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +020096yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020097{
David Sedlákc5b20842019-08-13 10:18:31 +020098 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +020099 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200100 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200101
David Sedlák94de2aa2019-02-15 12:42:11 +0100102#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
103#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100104#define IF_ARG_PREFIX_END }
105
David Sedlák1c8b2702019-02-22 11:03:02 +0100106 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100107 case 'c':
108 already_read += 1;
109 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200110 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200111
David Sedlák94de2aa2019-02-15 12:42:11 +0100112 case 'd':
113 already_read += 1;
114 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200115 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200116
David Sedlák94de2aa2019-02-15 12:42:11 +0100117 case 'm':
118 already_read += 1;
119 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200120 break;
121
David Sedlák94de2aa2019-02-15 12:42:11 +0100122 case 'n':
123 already_read += 1;
124 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200125 break;
126
David Sedlák94de2aa2019-02-15 12:42:11 +0100127 case 't':
128 already_read += 1;
129 IF_ARG_PREFIX("a", 1)
130 IF_ARG("g", 1, YIN_ARG_TAG)
131 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
132 IF_ARG_PREFIX_END
133 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200134 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200135
David Sedlák94de2aa2019-02-15 12:42:11 +0100136 case 'u':
137 already_read += 1;
138 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200139 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200140
David Sedlák94de2aa2019-02-15 12:42:11 +0100141 case 'v':
142 already_read += 1;
143 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200144 break;
145 }
146
David Sedlákc10e7902018-12-17 02:17:59 +0100147 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200148 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200149 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200150 }
151
David Sedlák18730132019-03-15 15:51:34 +0100152#undef IF_ARG
153#undef IF_ARG_PREFIX
154#undef IF_ARG_PREFIX_END
155
David Sedlák872c7b42018-10-26 13:15:20 +0200156 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200157}
158
David Sedlák4f03b932019-07-26 13:01:47 +0200159void free_arg_rec(struct yin_parser_ctx *ctx, struct yin_arg_record *record) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200160 (void)ctx; /* unused */
David Sedlákd2d676a2019-07-22 11:28:19 +0200161 if (record && record->dynamic_content) {
David Sedlák00250342019-06-21 14:19:39 +0200162 free(record->content);
163 }
164}
165
David Sedlák81497a32019-08-13 16:56:26 +0200166#define IS_NODE_ELEM(kw) (kw == YANG_ANYXML || kw == YANG_ANYDATA || kw == YANG_LEAF || kw == YANG_LEAF_LIST || \
167 kw == YANG_TYPEDEF || kw == YANG_USES || kw == YANG_LIST || kw == YANG_NOTIFICATION || \
168 kw == YANG_GROUPING || kw == YANG_CONTAINER || kw == YANG_CASE || kw == YANG_CHOICE || \
169 kw == YANG_ACTION || kw == YANG_RPC || kw == YANG_AUGMENT)
170
171#define HAS_META(kw) (IS_NODE_ELEM(kw) || kw == YANG_ARGUMENT || kw == YANG_IMPORT || kw == YANG_INCLUDE || kw == YANG_INPUT || kw == YANG_OUTPUT)
172
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 */
213 (*result)[i].type = va_arg(ap, enum yang_keyword);
214 /* 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;
222 } else if ((*result)[i].type == YANG_ARGUMENT) {
223 struct yin_argument_meta *arg_meta = NULL;
224 arg_meta = calloc(1, sizeof *arg_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200225 LY_CHECK_GOTO(!arg_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200226 arg_meta->argument = va_arg(ap, const char **);
227 arg_meta->flags = va_arg(ap, uint16_t *);
228 (*result)[i].dest = arg_meta;
229 } else if ((*result)[i].type == YANG_IMPORT) {
230 struct import_meta *imp_meta = NULL;
231 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200232 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200233 imp_meta->prefix = va_arg(ap, const char *);
234 imp_meta->imports = va_arg(ap, struct lysp_import **);
235 (*result)[i].dest = imp_meta;
236 } else if ((*result)[i].type == YANG_INCLUDE) {
237 struct include_meta *inc_meta = NULL;
238 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200239 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200240 inc_meta->name = va_arg(ap, const char *);
241 inc_meta->includes = va_arg(ap, struct lysp_include **);
242 (*result)[i].dest = inc_meta;
243 } else if ((*result)[i].type == YANG_INPUT || (*result)[i].type == YANG_OUTPUT) {
244 struct inout_meta *inout_meta = NULL;
245 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200246 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200247 inout_meta->parent = parent;
248 inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
249 (*result)[i].dest = inout_meta;
250 } else {
251 (*result)[i].dest = va_arg(ap, void *);
252 }
253 /* FLAGS */
254 (*result)[i].flags = va_arg(ap, int);
255 }
256 va_end(ap);
257
258 return LY_SUCCESS;
259
David Sedlákbf8a2b72019-08-14 16:48:10 +0200260mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200261 subelems_deallocator(count, *result);
262 LOGMEM(ctx->xml_ctx.ctx);
263 return LY_EMEM;
264}
265
David Sedlák8f7a1172019-06-20 14:42:18 +0200266LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200267yin_load_attributes(struct yin_parser_ctx *ctx, const char **data, struct yin_arg_record **attrs)
David Sedláka7406952019-04-05 10:33:07 +0200268{
269 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200270 struct yin_arg_record *argument_record = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +0200271 const char *prefix, *name;
272 size_t prefix_len, name_len;
David Sedláka7406952019-04-05 10:33:07 +0200273
David Sedlák555c7202019-07-04 12:14:12 +0200274 /* load all attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +0200275 while (ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákc5b20842019-08-13 10:18:31 +0200276 ret = lyxml_get_attribute(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák26ea1432019-08-14 13:42:23 +0200277 LY_CHECK_GOTO(ret, cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200278
David Sedlákda8ffa32019-07-08 14:17:10 +0200279 if (ctx->xml_ctx.status == LYXML_ATTR_CONTENT) {
280 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, *attrs, argument_record, ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +0200281 argument_record->name = name;
282 argument_record->name_len = name_len;
283 argument_record->prefix = prefix;
284 argument_record->prefix_len = prefix_len;
David Sedlákda8ffa32019-07-08 14:17:10 +0200285 ret = lyxml_get_string(&ctx->xml_ctx, data, &argument_record->content, &argument_record->content_len,
David Sedlák57715b12019-06-17 13:05:22 +0200286 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák26ea1432019-08-14 13:42:23 +0200287 LY_CHECK_GOTO(ret, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200288 }
289 }
290
David Sedlák8f7a1172019-06-20 14:42:18 +0200291cleanup:
292 if (ret != LY_SUCCESS) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200293 FREE_ARRAY(ctx, *attrs, free_arg_rec);
David Sedlákb4e44562019-07-04 15:42:12 +0200294 *attrs = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200295 }
296 return ret;
297}
298
David Sedlák4a650532019-07-10 11:55:18 +0200299LY_ERR
300yin_validate_value(struct yin_parser_ctx *ctx, enum yang_arg val_type, char *val, size_t len)
301{
302 int prefix = 0;
303 unsigned int c;
304 size_t utf8_char_len;
305 size_t already_read = 0;
306 while (already_read < len) {
307 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
308 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
309 already_read += utf8_char_len;
310 LY_CHECK_ERR_RET(already_read > len, LOGINT(ctx->xml_ctx.ctx), LY_EINT);
311
312 switch (val_type) {
313 case Y_IDENTIF_ARG:
314 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
315 break;
316 case Y_PREF_IDENTIF_ARG:
317 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
318 break;
319 case Y_STR_ARG:
320 case Y_MAYBE_STR_ARG:
321 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
322 break;
323 }
324 }
325
326 return LY_SUCCESS;
327}
328
David Sedlákb4e44562019-07-04 15:42:12 +0200329/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200330 * @brief Parse yin attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200331 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200332 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200333 * @param[in] attrs ([Sized array](@ref sizedarrays)) of attributes.
David Sedlák4a650532019-07-10 11:55:18 +0200334 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
335 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200336 * @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 +0200337 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200338 * @param[in] current_element Identification of current element, used for logging.
339 *
340 * @return LY_ERR values.
341 */
342static LY_ERR
David Sedlákc5b20842019-08-13 10:18:31 +0200343yin_parse_attribute(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, enum yin_argument arg_type,
David Sedlák292763b2019-07-09 11:10:53 +0200344 const char **arg_val, enum yang_arg val_type, enum yang_keyword current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200345{
David Sedlákc5b20842019-08-13 10:18:31 +0200346 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák8f7a1172019-06-20 14:42:18 +0200347 struct yin_arg_record *iter = NULL;
David Sedlák619db942019-07-03 14:47:30 +0200348 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200349
David Sedlák1bccdfa2019-06-17 15:55:27 +0200350 /* validation of attributes */
David Sedlák1f90d252019-07-10 17:09:32 +0200351 LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
David Sedlák00250342019-06-21 14:19:39 +0200352 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
353 if (!iter->prefix) {
David Sedlák060b00e2019-06-19 11:12:06 +0200354 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200355 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200356 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200357 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200358 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
David Sedlák292763b2019-07-09 11:10:53 +0200359 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200360 found = true;
David Sedlák4a650532019-07-10 11:55:18 +0200361 LY_CHECK_RET(yin_validate_value(ctx, val_type, iter->content, iter->content_len));
David Sedlák57715b12019-06-17 13:05:22 +0200362 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200363 *arg_val = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
David Sedlák619db942019-07-03 14:47:30 +0200364 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák00250342019-06-21 14:19:39 +0200365 /* string is no longer supposed to be freed when the sized array is freed */
366 iter->dynamic_content = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200367 } else {
David Sedlák99295322019-07-17 11:34:18 +0200368 if (iter->content_len == 0) {
369 *arg_val = lydict_insert(ctx->xml_ctx.ctx, "", 0);
370 } else {
371 *arg_val = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
David Sedlák99295322019-07-17 11:34:18 +0200372 }
David Sedlák26ea1432019-08-14 13:42:23 +0200373 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák57715b12019-06-17 13:05:22 +0200374 }
David Sedlák2b214ac2019-06-06 16:11:03 +0200375 } else {
David Sedlák1538a842019-08-08 15:38:51 +0200376 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 +0200377 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200378 }
379 }
380 }
381
David Sedlák292763b2019-07-09 11:10:53 +0200382 /* anything else than Y_MAYBE_STR_ARG is mandatory */
383 if (val_type != Y_MAYBE_STR_ARG && !found) {
David Sedlák9c40a922019-07-08 17:04:43 +0200384 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 +0200385 return LY_EVALID;
386 }
387
388 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200389}
390
David Sedlákd6e56892019-07-01 15:40:24 +0200391/**
David Sedlákda8ffa32019-07-08 14:17:10 +0200392 * @brief Get record with given type. Array must be sorted in ascending order by array[n].type.
David Sedlákd6e56892019-07-01 15:40:24 +0200393 *
394 * @param[in] type Type of wanted record.
395 * @param[in] array_size Size of array.
396 * @param[in] array Searched array.
397 *
398 * @return Pointer to desired record on success, NULL if element is not in the array.
399 */
David Sedlákb4e44562019-07-04 15:42:12 +0200400static struct yin_subelement *
David Sedlákb0faad82019-07-04 14:28:59 +0200401get_record(enum yang_keyword type, signed char array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200402{
David Sedlákb0faad82019-07-04 14:28:59 +0200403 signed char left = 0, right = array_size - 1, middle;
404
405 while (left <= right) {
406 middle = left + (right - left) / 2;
407
408 if (array[middle].type == type) {
409 return &array[middle];
410 }
411
412 if (array[middle].type < type) {
413 left = middle + 1;
414 } else {
415 right = middle - 1;
David Sedlákd6e56892019-07-01 15:40:24 +0200416 }
417 }
418
419 return NULL;
420}
421
David Sedlákbba38e52019-07-09 15:20:01 +0200422/**
423 * @brief Helper function to check mandatory constraint of subelement.
424 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200425 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200426 * @param[in] subelem_info Array of information about subelements.
427 * @param[in] subelem_info_size Size of subelem_info array.
428 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
429 *
430 * @return LY_ERR values.
431 */
432static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200433yin_check_subelem_mandatory_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedlákb0faad82019-07-04 14:28:59 +0200434 signed char subelem_info_size, enum yang_keyword current_element)
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ák5545f5d2019-07-11 11:55:16 +0200437 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
David Sedlák21f87cd2019-07-03 16:53:23 +0200438 if (subelem_info[i].flags & YIN_SUBELEM_MANDATORY && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200439 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200440 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200441 return LY_EVALID;
442 }
443 }
444
445 return LY_SUCCESS;
446}
447
David Sedlákbba38e52019-07-09 15:20:01 +0200448/**
449 * @brief Helper function to check "first" constraint of subelement.
450 *
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] subelem_info Array of information about subelements.
453 * @param[in] subelem_info_size Size of subelem_info array.
454 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200455 * @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 +0200456 *
457 * @return LY_ERR values.
458 */
459static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200460yin_check_subelem_first_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedláke1a30302019-07-10 13:49:38 +0200461 signed char subelem_info_size, enum yang_keyword current_element,
462 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200463{
David Sedlákb0faad82019-07-04 14:28:59 +0200464 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200465 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200466 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
467 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200468 return LY_EVALID;
469 }
470 }
471
472 return LY_SUCCESS;
473}
474
David Sedlákbba38e52019-07-09 15:20:01 +0200475/**
476 * @brief Helper function to check if array of information about subelements is in ascending order.
477 *
478 * @param[in] subelem_info Array of information about subelements.
479 * @param[in] subelem_info_size Size of subelem_info array.
480 *
481 * @return True iff subelem_info array is in ascending order, False otherwise.
482 */
David Sedlák5545f5d2019-07-11 11:55:16 +0200483#ifndef NDEBUG
David Sedlákbba38e52019-07-09 15:20:01 +0200484static bool
David Sedlákb0faad82019-07-04 14:28:59 +0200485is_ordered(struct yin_subelement *subelem_info, signed char subelem_info_size)
486{
David Sedlák292763b2019-07-09 11:10:53 +0200487 enum yang_keyword current = YANG_NONE; /* 0 (minimal value) */
David Sedlákb0faad82019-07-04 14:28:59 +0200488
489 for (signed char i = 0; i < subelem_info_size; ++i) {
490 if (subelem_info[i].type <= current) {
491 return false;
492 }
493 current = subelem_info[i].type;
494 }
495
496 return true;
497}
David Sedlák5545f5d2019-07-11 11:55:16 +0200498#endif
David Sedlákb0faad82019-07-04 14:28:59 +0200499
David Sedlákd6e56892019-07-01 15:40:24 +0200500/**
David Sedlákb4e44562019-07-04 15:42:12 +0200501 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
502 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200503 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200504 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200505 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákd6e56892019-07-01 15:40:24 +0200506 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákb4e44562019-07-04 15:42:12 +0200507 * @param[in] kw Type of current element.
508 * @param[out] value Where value of attribute should be stored.
509 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200510 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200511 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200512 *
David Sedlákd6e56892019-07-01 15:40:24 +0200513 * @return LY_ERR values.
514 */
David Sedlákb4e44562019-07-04 15:42:12 +0200515static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200516yin_parse_simple_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
David Sedlákc5b20842019-08-13 10:18:31 +0200517 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 +0200518{
David Sedlák1f90d252019-07-10 17:09:32 +0200519 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200520 struct yin_subelement subelems[1] = {
521 {YANG_CUSTOM, NULL, 0}
522 };
David Sedlákb4e44562019-07-04 15:42:12 +0200523
David Sedlákda8ffa32019-07-08 14:17:10 +0200524 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200525}
526
527/**
David Sedlák6542aed2019-08-14 10:47:43 +0200528 * @brief Parse path element.
529 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200530 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200531 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
532 * @param[in,out] data Data to read from, always moved to currently handled character.
533 * @param[in] kw Type of current element.
534 * @param[out] type Type structure to store parsed value, flags and extension instances.
535 *
536 * @return LY_ERR values.
537 */
538static LY_ERR
539yin_parse_path(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
540 struct lysp_type *type)
541{
542 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
543 YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
544 type->flags |= LYS_SET_PATH;
545
546 return LY_SUCCESS;
547}
548
549/**
David Sedlákd3983112019-07-12 11:20:56 +0200550 * @brief Parse pattern element.
551 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200552 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd3983112019-07-12 11:20:56 +0200553 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
554 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200555 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200556 *
557 * @return LY_ERR values.
558 */
559static LY_ERR
560yin_parse_pattern(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
561 struct lysp_type *type)
562{
563 const char *real_value = NULL;
564 char *saved_value = NULL;
565 struct lysp_restr *restr;
566
567 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->patterns, restr, LY_EMEM);
568 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &real_value, Y_STR_ARG, YANG_PATTERN));
569 size_t len = strlen(real_value);
570
571 saved_value = malloc(len + 2);
572 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
573 memmove(saved_value + 1, real_value, len);
574 FREE_STRING(ctx->xml_ctx.ctx, real_value);
575 saved_value[0] = 0x06;
576 saved_value[len + 1] = '\0';
577 restr->arg = lydict_insert_zc(ctx->xml_ctx.ctx, saved_value);
578 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
579 type->flags |= LYS_SET_PATTERN;
580
581 struct yin_subelement subelems[6] = {
582 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
583 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
584 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
585 {YANG_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
586 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
587 {YANG_CUSTOM, NULL, 0}
588 };
589 return yin_parse_content(ctx, subelems, 6, data, YANG_PATTERN, NULL, &restr->exts);
590}
591
David Sedlákc5b20842019-08-13 10:18:31 +0200592/**
593 * @brief Parse fraction-digits element.
594 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200595 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200596 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
597 * @param[in,out] data Data to read from, always moved to currently handled character.
598 * @param[in,out] type Type structure to store value, flags and extension instances.
599 *
600 * @return LY_ERR values.
601 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200602static LY_ERR
603yin_parse_fracdigits(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
604 struct lysp_type *type)
605{
606 const char *temp_val = NULL;
607 char *ptr;
608 unsigned long int num;
609
610 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_FRACTION_DIGITS));
611
612 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200613 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200614 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
615 return LY_EVALID;
616 }
617
618 errno = 0;
619 num = strtoul(temp_val, &ptr, 10);
620 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200621 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200622 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
623 return LY_EVALID;
624 }
625 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200626 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200627 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
628 return LY_EVALID;
629 }
David Sedlák2ab5d8e2019-07-16 11:19:41 +0200630 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200631 type->fraction_digits = num;
632 type->flags |= LYS_SET_FRDIGITS;
633 struct yin_subelement subelems[1] = {
David Sedlákd1144562019-08-06 12:36:14 +0200634 {YANG_CUSTOM, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200635 };
636 return yin_parse_content(ctx, subelems, 1, data, YANG_FRACTION_DIGITS, NULL, &type->exts);
637}
638
David Sedlák07869a52019-07-12 14:28:19 +0200639/**
David Sedlák43801c92019-08-05 15:58:54 +0200640 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200641 *
642 * @param[in,out] ctx YIN parser context for logging and to store current state.
643 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
644 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200645 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200646 *
647 * @return LY_ERR values.
648 */
David Sedlákca36c422019-07-12 12:47:55 +0200649static LY_ERR
David Sedlák43801c92019-08-05 15:58:54 +0200650yin_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 +0200651{
David Sedlák07869a52019-07-12 14:28:19 +0200652 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200653
David Sedlák43801c92019-08-05 15:58:54 +0200654 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->enums, en, LY_EMEM);
655 type->flags |= LYS_SET_ENUM;
656 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_ENUM));
657 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
658 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
659 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200660
661 struct yin_subelement subelems[6] = {
David Sedlák07869a52019-07-12 14:28:19 +0200662 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
663 {YANG_IF_FEATURE, &en->iffeatures, 0},
David Sedlák07869a52019-07-12 14:28:19 +0200664 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
665 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
David Sedlák43801c92019-08-05 15:58:54 +0200666 {YANG_VALUE, en, YIN_SUBELEM_UNIQUE},
David Sedlákca36c422019-07-12 12:47:55 +0200667 {YANG_CUSTOM, NULL, 0}
668 };
David Sedlák43801c92019-08-05 15:58:54 +0200669 return yin_parse_content(ctx, subelems, 6, data, YANG_ENUM, NULL, &en->exts);
670}
671
672/**
673 * @brief Parse bit element.
674 *
675 * @param[in,out] ctx YIN parser context for logging and to store current state.
676 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
677 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200678 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200679 *
680 * @return LY_ERR values.
681 */
682static LY_ERR
683yin_parse_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
684 struct lysp_type *type)
685{
686 struct lysp_type_enum *en;
687
688 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->bits, en, LY_EMEM);
689 type->flags |= LYS_SET_BIT;
690 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_BIT));
691 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
692
693 struct yin_subelement subelems[6] = {
694 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
695 {YANG_IF_FEATURE, &en->iffeatures, 0},
696 {YANG_POSITION, en, YIN_SUBELEM_UNIQUE},
697 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
698 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
699 {YANG_CUSTOM, NULL, 0}
700 };
701 return yin_parse_content(ctx, subelems, 6, data, YANG_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200702}
703
David Sedlákd3983112019-07-12 11:20:56 +0200704/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200705 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
706 * more instances, such as base or if-feature.
707 *
708 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200709 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200710 * @param[in,out] data Data to read from, always moved to currently handled character.
711 * @param[in] kw Type of current element.
712 * @param[out] values Parsed values to add to.
713 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200714 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200715 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200716 *
717 * @return LY_ERR values.
718 */
719static LY_ERR
720yin_parse_simple_elements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
David Sedlákc5b20842019-08-13 10:18:31 +0200721 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 +0200722{
723 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200724 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200725 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200726 struct yin_subelement subelems[1] = {
727 {YANG_CUSTOM, &index, 0}
728 };
729
David Sedlák1f90d252019-07-10 17:09:32 +0200730 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200731
732 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
733}
734
735/**
David Sedlák6542aed2019-08-14 10:47:43 +0200736 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
737 *
738 * @param[in,out] ctx YIN parser context for logging and to store current state.
739 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
740 * @param[in,out] data Data to read from, always moved to currently handled character.
741 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200742 * @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 +0200743 * @param[in] arg_type Expected type of attribute.
744 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200745 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200746 *
747 * @return LY_ERR values.
748 */
749static LY_ERR
750yin_parse_simple_elem(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
751 struct yin_subelement *subinfo, enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
752{
753 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
754 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subinfo->dest,
755 arg_type, arg_val_type, exts));
756 } else {
757 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subinfo->dest,
758 arg_type, arg_val_type, exts));
759 }
760
761 return LY_SUCCESS;
762}
763
764/**
765 * @brief Parse base element.
766 *
767 * @param[in,out] ctx YIN parser context for logging and to store current state.
768 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
769 * @param[in,out] data Data to read from, always moved to currently handled character.
770 * @param[in] parent Identification of parent element.
771 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200772 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200773 *
774 * @return LY_ERR values.
775 */
776static LY_ERR
777yin_parse_base(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword parent,
778 void *dest, struct lysp_ext_instance **exts)
779{
780 struct lysp_type *type = NULL;
781
782 if (parent == YANG_TYPE) {
783 type = (struct lysp_type *)dest;
784 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, YANG_BASE, &type->bases, YIN_ARG_NAME,
785 Y_PREF_IDENTIF_ARG, exts));
786 type->flags |= LYS_SET_BASE;
787 } else if (parent == YANG_IDENTITY) {
788 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, YANG_BASE, (const char ***)dest,
789 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
790 } else {
791 LOGINT(ctx->xml_ctx.ctx);
792 return LY_EINT;
793 }
794
795 return LY_SUCCESS;
796}
797
798/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200799 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200800 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200801 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákcf5569a2019-07-11 13:31:34 +0200802 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
803 * @param[in,out] data Data to read from, always moved to currently handled character.
804 * @prama[out] type Type structure to store value, flag and extensions.
805 *
806 * @return LY_ERR values.
807 */
808static LY_ERR
809yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
810 const char **data, struct lysp_type *type)
811{
812 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200813 struct yin_subelement subelems[1] = {
814 {YANG_CUSTOM, NULL, 0}
815 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200816
817 type->flags |= LYS_SET_REQINST;
818 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_REQUIRE_INSTANCE));
819 if (strcmp(temp_val, "true") == 0) {
820 type->require_instance = 1;
821 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200822 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
823 "require-instance", "true", "false");
David Sedlákcf5569a2019-07-11 13:31:34 +0200824 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
825 return LY_EVALID;
826 }
827 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
828
829 return yin_parse_content(ctx, subelems, 1, data, YANG_REQUIRE_INSTANCE, NULL, &type->exts);
830}
831
832/**
David Sedlákce77bf52019-07-11 16:59:31 +0200833 * @brief Parse modifier element.
834 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200835 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200836 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
837 * @param[in,out] data Data to read from, always moved to currently handled character.
838 * @param[in,out] pat Value to write to.
839 * @param[in,out] exts Extension instances to add to.
840 *
841 * @return LY_ERR values.
842 */
843static LY_ERR
844yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
845 const char **pat, struct lysp_ext_instance **exts)
846{
David Sedlákd3983112019-07-12 11:20:56 +0200847 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200848 const char *temp_val;
849 char *modified_val;
850 struct yin_subelement subelems[1] = {
851 {YANG_CUSTOM, NULL, 0}
852 };
853
854 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MODIFIER));
855 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200856 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
857 "modifier", "invert-match");
David Sedlákce77bf52019-07-11 16:59:31 +0200858 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
859 return LY_EVALID;
860 }
David Sedlákd3983112019-07-12 11:20:56 +0200861 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200862
863 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200864 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200865 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200866 strcpy(modified_val, *pat);
867 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200868
869 /* modify the new value */
870 modified_val[0] = 0x15;
871 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
872
873 return yin_parse_content(ctx, subelems, 1, data, YANG_MODIFIER, NULL, exts);
874}
875
876/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200877 * @brief Parse a restriction element (length, range or one instance of must).
878 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200879 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb7296dd2019-07-11 14:58:38 +0200880 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
881 * @param[in,out] data Data to read from, always moved to currently handled character.
882 * @param[in] restr_kw Identificaton of element that is being parsed, can be set to YANG_MUST, YANG_LENGTH or YANG_RANGE.
David Sedlák6542aed2019-08-14 10:47:43 +0200883 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200884 */
885static LY_ERR
886yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
887 enum yang_keyword restr_kw, struct lysp_restr *restr)
888{
889 assert(restr_kw == YANG_MUST || restr_kw == YANG_LENGTH || restr_kw == YANG_RANGE);
890 struct yin_subelement subelems[5] = {
David Sedlák968ac342019-07-11 15:17:59 +0200891 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
892 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
893 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
894 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
895 {YANG_CUSTOM, NULL, 0}
896 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200897 /* argument of must is called condition, but argument of length and range is called value */
David Sedlákc5b20842019-08-13 10:18:31 +0200898 enum yin_argument arg_type = (restr_kw == YANG_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200899 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
900
901 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
902}
903
904/**
David Sedlák6542aed2019-08-14 10:47:43 +0200905 * @brief Parse range element.
906 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200907 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200908 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
909 * @param[in,out] data Data to read from, always moved to currently handled character.
910 * @param[out] type Type structure to store parsed value and flags.
911 *
912 * @return LY_ERR values.
913 */
914static LY_ERR
915yin_parse_range(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
916 const char **data, struct lysp_type *type)
917{
918 type->range = calloc(1, sizeof *type->range);
919 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
920 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, YANG_RANGE, type->range));
921 type->flags |= LYS_SET_RANGE;
922
923 return LY_SUCCESS;
924}
925
926/**
927 * @brief Parse length element.
928 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200929 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200930 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
931 * @param[in,out] data Data to read from, always moved to currently handled character.
932 * @param[out] type Type structure to store parsed value and flags.
933 *
934 * @return LY_ERR values.
935 */
936static LY_ERR
937yin_parse_length(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
938 const char **data, struct lysp_type *type)
939{
940 type->length = calloc(1, sizeof *type->length);
941 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
942 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, YANG_LENGTH, type->length));
943 type->flags |= LYS_SET_LENGTH;
944
945 return LY_SUCCESS;
946}
947
948/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200949 * @brief Parse must element.
950 *
951 * @param[in,out] ctx YIN parser context for logging and to store current state.
952 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
953 * @param[in,out] data Data to read from, always moved to currently handled character.
954 * @param[in,out] restrs Restrictions to add to.
955 *
956 * @return LY_ERR values.
957 */
958static LY_ERR
959yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
960{
961 struct lysp_restr *restr;
962
963 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
964 return yin_parse_restriction(ctx, attrs, data, YANG_MUST, restr);
965}
966
967/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200968 * @brief Parse position or value element.
969 *
970 * @param[in,out] ctx YIN parser context for logging and to store current state.
971 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
972 * @param[in,out] data Data to read from, always moved to currently handled character.
973 * @param[in] kw Type of current element, can be set to YANG_POSITION or YANG_VALUE.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200974 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200975 *
976 * @return LY_ERR values.
977 */
978static LY_ERR
979yin_parse_value_pos_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
980 enum yang_keyword kw, struct lysp_type_enum *enm)
981{
982 assert(kw == YANG_POSITION || kw == YANG_VALUE);
983 const char *temp_val = NULL;
984 char *ptr;
985 long int num;
986 unsigned long int unum;
987
988 /* set value flag */
989 enm->flags |= LYS_SET_VALUE;
990
991 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200992 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 +0200993 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
994 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == YANG_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200995 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +0200996 goto error;
997 }
998
999 /* convert value */
1000 errno = 0;
1001 if (kw == YANG_VALUE) {
1002 num = strtol(temp_val, &ptr, 10);
1003 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +02001004 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 +02001005 goto error;
1006 }
1007 } else {
1008 unum = strtoul(temp_val, &ptr, 10);
1009 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +02001010 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 +02001011 goto error;
1012 }
1013 }
1014 /* check if whole argument value was converted */
1015 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001016 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 +02001017 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +02001018 }
1019 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +02001020 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 +02001021 goto error;
1022 }
1023 /* save correctly ternary operator can't be used because num and unum have different signes */
1024 if (kw == YANG_VALUE) {
1025 enm->value = num;
1026 } else {
1027 enm->value = unum;
1028 }
1029 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1030
1031 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +02001032 struct yin_subelement subelems[1] = {
1033 {YANG_CUSTOM, NULL, 0}
1034 };
David Sedlák5545f5d2019-07-11 11:55:16 +02001035 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
1036
David Sedlákbf8a2b72019-08-14 16:48:10 +02001037error:
David Sedlák5545f5d2019-07-11 11:55:16 +02001038 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1039 return LY_EVALID;
1040}
1041
David Sedlák05404f62019-07-24 14:11:53 +02001042
1043/**
1044 * @brief Parse belongs-to element.
1045 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001046 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001047 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1048 * @param[in,out] data Data to read from, always moved to currently handled character.
1049 * @param[out] submod Structure of submodule that is being parsed.
1050 * @param[in,out] exts Extension instances to add to.
1051 *
1052 * @return LY_ERR values
1053 */
1054static LY_ERR
1055yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1056 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
1057{
1058 struct yin_subelement subelems[2] = {
1059 {YANG_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1060 {YANG_CUSTOM, NULL, 0}
1061 };
1062 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, YANG_BELONGS_TO));
1063
1064 return yin_parse_content(ctx, subelems, 2, data, YANG_BELONGS_TO, NULL, exts);
1065}
1066
David Sedlák5545f5d2019-07-11 11:55:16 +02001067/**
David Sedlákc1771b12019-07-10 15:55:46 +02001068 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001069 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001070 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001071 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001072 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákcf5569a2019-07-11 13:31:34 +02001073 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001074 * @param[in] elem_type Type of element can be set to YANG_ORGANIZATION or YANG_CONTACT or YANG_DESCRIPTION or YANG_REFERENCE.
David Sedlákb4e44562019-07-04 15:42:12 +02001075 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001076 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001077 *
1078 * @return LY_ERR values.
1079 */
1080static LY_ERR
David Sedlákdf2a9732019-08-07 13:23:16 +02001081yin_parse_meta_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1082 enum yang_keyword elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +02001083{
1084 assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
1085
David Sedlák968ac342019-07-11 15:17:59 +02001086 struct yin_subelement subelems[2] = {
1087 {YANG_CUSTOM, NULL, 0},
1088 {YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1089 };
David Sedlákdf2a9732019-08-07 13:23:16 +02001090 /* check attributes */
1091 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 +02001092
David Sedlákdf2a9732019-08-07 13:23:16 +02001093 /* parse content */
David Sedlákda8ffa32019-07-08 14:17:10 +02001094 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001095}
1096
1097/**
David Sedlákc1771b12019-07-10 15:55:46 +02001098 * @brief Parse error-message element.
1099 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001100 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001101 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákc1771b12019-07-10 15:55:46 +02001102 * @param[in,out] data Data to read from.
1103 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001104 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001105 *
1106 * @return LY_ERR values.
1107 */
1108static LY_ERR
David Sedlákdf2a9732019-08-07 13:23:16 +02001109yin_parse_err_msg_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1110 const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +02001111{
David Sedlák968ac342019-07-11 15:17:59 +02001112 struct yin_subelement subelems[2] = {
1113 {YANG_CUSTOM, NULL, 0},
1114 {YIN_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1115 };
David Sedlákc1771b12019-07-10 15:55:46 +02001116
David Sedlákdf2a9732019-08-07 13:23:16 +02001117 /* check attributes */
1118 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, YANG_ERROR_MESSAGE));
1119
David Sedlákc1771b12019-07-10 15:55:46 +02001120 return yin_parse_content(ctx, subelems, 2, data, YANG_ERROR_MESSAGE, NULL, exts);
1121}
1122
1123/**
David Sedlák6542aed2019-08-14 10:47:43 +02001124 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001125 *
1126 * @param[in,out] ctx YIN parser context for logging and to store current state.
1127 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1128 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák6542aed2019-08-14 10:47:43 +02001129 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001130 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001131 *
1132 * @return LY_ERR values.
1133 */
1134static LY_ERR
David Sedlák6542aed2019-08-14 10:47:43 +02001135yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1136 enum yang_keyword parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001137{
David Sedlák6542aed2019-08-14 10:47:43 +02001138 struct lysp_type *type = NULL;
1139 if (parent == YANG_DEVIATE) {
1140 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
1141 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1142 type = *((struct lysp_type **)subinfo->dest);
1143 } else {
1144 type = (struct lysp_type *)subinfo->dest;
1145 }
1146 /* type as child of another type */
1147 if (parent == YANG_TYPE) {
1148 struct lysp_type *nested_type = NULL;
1149 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->types, nested_type, LY_EMEM);
1150 type->flags |= LYS_SET_TYPE;
1151 type = nested_type;
1152 }
David Sedlák374d2b32019-07-17 15:06:55 +02001153 struct yin_subelement subelems[11] = {
1154 {YANG_BASE, type, 0},
1155 {YANG_BIT, type, 0},
1156 {YANG_ENUM, type, 0},
1157 {YANG_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1158 {YANG_LENGTH, type, YIN_SUBELEM_UNIQUE},
1159 {YANG_PATH, type, YIN_SUBELEM_UNIQUE},
1160 {YANG_PATTERN, type, 0},
1161 {YANG_RANGE, type, YIN_SUBELEM_UNIQUE},
1162 {YANG_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1163 {YANG_TYPE, type},
1164 {YANG_CUSTOM, NULL, 0},
1165 };
1166 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, YANG_TYPE));
1167 return yin_parse_content(ctx, subelems, 11, data, YANG_TYPE, NULL, &type->exts);
1168}
1169
David Sedlák1af868e2019-07-17 17:03:14 +02001170/**
1171 * @brief Parse max-elements element.
1172 *
1173 * @param[in,out] ctx YIN parser context for logging and to store current state.
1174 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1175 * @param[in,out] data Data to read from, always moved to currently handled character.
1176 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001177 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001178 * @param[in,out] exts Extension instances to add to.
1179 *
1180 * @return LY_ERR values.
1181 */
1182static LY_ERR
1183yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
1184 uint16_t *flags, struct lysp_ext_instance **exts)
1185{
1186 const char *temp_val = NULL;
1187 char *ptr;
1188 unsigned long int num;
1189 struct yin_subelement subelems[1] = {
1190 {YANG_CUSTOM, NULL, 0},
1191 };
David Sedlák374d2b32019-07-17 15:06:55 +02001192
David Sedlák1af868e2019-07-17 17:03:14 +02001193 *flags |= LYS_SET_MAX;
1194 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MAX_ELEMENTS));
1195 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 +02001196 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001197 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1198 return LY_EVALID;
1199 }
1200
1201 if (strcmp(temp_val, "unbounded")) {
1202 errno = 0;
1203 num = strtoul(temp_val, &ptr, 10);
1204 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001205 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001206 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1207 return LY_EVALID;
1208 }
1209 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001210 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001211 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1212 return LY_EVALID;
1213 }
1214 *max = num;
1215 }
1216 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1217 return yin_parse_content(ctx, subelems, 1, data, YANG_MAX_ELEMENTS, NULL, exts);
1218}
David Sedlák374d2b32019-07-17 15:06:55 +02001219
1220/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001221 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001222 *
1223 * @param[in,out] ctx YIN parser context for logging and to store current state.
1224 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1225 * @param[in,out] data Data to read from, always moved to currently handled character.
1226 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001227 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001228 * @param[in,out] exts Extension instances to add to.
1229 *
1230 * @return LY_ERR values.
1231 */
1232static LY_ERR
1233yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
1234 uint16_t *flags, struct lysp_ext_instance **exts)
1235{
1236 const char *temp_val = NULL;
1237 char *ptr;
1238 unsigned long int num;
1239 struct yin_subelement subelems[1] = {
1240 {YANG_CUSTOM, NULL, 0},
1241 };
1242
1243 *flags |= LYS_SET_MIN;
David Sedláka2dad212019-07-18 12:45:19 +02001244 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MIN_ELEMENTS));
David Sedlák09e18c92019-07-18 11:17:11 +02001245
1246 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001247 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001248 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1249 return LY_EVALID;
1250 }
1251
1252 errno = 0;
1253 num = strtoul(temp_val, &ptr, 10);
1254 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001255 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001256 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1257 return LY_EVALID;
1258 }
1259 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001260 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001261 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1262 return LY_EVALID;
1263 }
1264 *min = num;
1265 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001266 return yin_parse_content(ctx, subelems, 1, data, YANG_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001267}
1268
David Sedláka2dad212019-07-18 12:45:19 +02001269/**
1270 * @brief Parse min-elements or max-elements element.
1271 *
1272 * @param[in,out] ctx YIN parser context for logging and to store current state.
1273 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1274 * @param[in,out] data Data to read from, always moved to currently handled character.
1275 * @param[in] parent Identification of parent element.
1276 * @param[in] current Identification of current element.
1277 * @param[in] dest Where the parsed value and flags should be stored.
1278 *
1279 * @return LY_ERR values.
1280 */
David Sedlák09e18c92019-07-18 11:17:11 +02001281static LY_ERR
1282yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1283 enum yang_keyword parent, enum yang_keyword current, void *dest)
1284{
1285 assert(current == YANG_MAX_ELEMENTS || current == YANG_MIN_ELEMENTS);
David Sedlák4ffcec82019-07-25 15:10:21 +02001286 assert(parent == YANG_LEAF_LIST || parent == YANG_REFINE || parent == YANG_LIST || parent == YANG_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001287 uint32_t *lim;
1288 uint16_t *flags;
1289 struct lysp_ext_instance **exts;
1290
1291 if (parent == YANG_LEAF_LIST) {
1292 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
1293 flags = &((struct lysp_node_leaflist *)dest)->flags;
1294 exts = &((struct lysp_node_leaflist *)dest)->exts;
1295 } else if (parent == YANG_REFINE) {
1296 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
1297 flags = &((struct lysp_refine *)dest)->flags;
1298 exts = &((struct lysp_refine *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001299 } else if (parent == YANG_LIST) {
David Sedlák09e18c92019-07-18 11:17:11 +02001300 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
1301 flags = &((struct lysp_node_list *)dest)->flags;
1302 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001303 } else {
1304 lim = ((struct minmax_dev_meta *)dest)->lim;
1305 flags = ((struct minmax_dev_meta *)dest)->flags;
1306 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001307 }
1308
1309 if (current == YANG_MAX_ELEMENTS) {
1310 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1311 } else {
1312 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1313 }
1314
1315 return LY_SUCCESS;
1316}
1317
1318/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001319 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001320 *
1321 * @param[in,out] ctx YIN parser context for logging and to store current state.
1322 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1323 * @param[in,out] data Data to read from, always moved to currently handled character.
1324 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001325 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001326 *
1327 * @return LY_ERR values.
1328 */
1329static LY_ERR
1330yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1331 uint16_t *flags, struct lysp_ext_instance **exts)
1332{
1333 const char *temp_val;
1334 struct yin_subelement subelems[1] = {
1335 {YANG_CUSTOM, NULL, 0},
1336 };
1337
1338 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_ORDERED_BY));
1339 if (strcmp(temp_val, "system") == 0) {
1340 *flags |= LYS_ORDBY_SYSTEM;
1341 } else if (strcmp(temp_val, "user") == 0) {
1342 *flags |= LYS_ORDBY_USER;
1343 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001344 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1345 "ordered-by", "system", "user");
David Sedláka2dad212019-07-18 12:45:19 +02001346 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1347 return LY_EVALID;
1348 }
1349 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1350
1351 return yin_parse_content(ctx, subelems, 1, data, YANG_ORDERED_BY, NULL, exts);
1352}
1353
1354/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001355 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001356 *
1357 * @param[in,out] ctx YIN parser context for logging and to store current state.
1358 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1359 * @param[in,out] data Data to read from, always moved to currently handled character.
1360 * @param[in] any_kw Identification of current element, can be set to YANG_ANY_DATA or YANG_ANY_XML
David Sedlákad83cf92019-08-13 12:53:53 +02001361 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001362 *
1363 * @return LY_ERR values.
1364 */
1365static LY_ERR
1366yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1367 enum yang_keyword any_kw, struct tree_node_meta *node_meta)
1368{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001369 struct lysp_node_anydata *any;
1370
David Sedlák8d552d62019-08-06 15:29:05 +02001371 /* create new sibling */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001372 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, any, next);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001373 any->nodetype = (any_kw == YANG_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
1374 any->parent = node_meta->parent;
1375
David Sedlákbf8a2b72019-08-14 16:48:10 +02001376 /* parse argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001377 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 +02001378
1379 struct yin_subelement subelems[9] = {
1380 {YANG_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1381 {YANG_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1382 {YANG_IF_FEATURE, &any->iffeatures, 0},
1383 {YANG_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1384 {YANG_MUST, &any->musts, 0},
1385 {YANG_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1386 {YANG_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1387 {YANG_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1388 {YANG_CUSTOM, NULL, 0},
1389 };
1390 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1391}
1392
1393/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001394 * @brief parse leaf element.
1395 *
1396 * @param[in,out] ctx YIN parser context for logging and to store current state.
1397 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1398 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001399 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001400 *
1401 * @return LY_ERR values.
1402 */
1403static LY_ERR
1404yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1405 struct tree_node_meta *node_meta)
1406{
David Sedlák203ca3a2019-07-18 15:26:25 +02001407 struct lysp_node_leaf *leaf;
1408
David Sedlák8d552d62019-08-06 15:29:05 +02001409 /* create structure new leaf */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001410 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, leaf, next);
David Sedlák203ca3a2019-07-18 15:26:25 +02001411 leaf->nodetype = LYS_LEAF;
1412 leaf->parent = node_meta->parent;
1413
David Sedlák203ca3a2019-07-18 15:26:25 +02001414 /* parser argument */
1415 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, YANG_LEAF));
1416
1417 /* parse content */
1418 struct yin_subelement subelems[12] = {
1419 {YANG_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1420 {YANG_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1421 {YANG_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1422 {YANG_IF_FEATURE, &leaf->iffeatures, 0},
1423 {YANG_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1424 {YANG_MUST, &leaf->musts, 0},
1425 {YANG_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1426 {YANG_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1427 {YANG_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1428 {YANG_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1429 {YANG_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1430 {YANG_CUSTOM, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001431 };
David Sedlák203ca3a2019-07-18 15:26:25 +02001432 return yin_parse_content(ctx, subelems, 12, data, YANG_LEAF, NULL, &leaf->exts);
1433}
1434
1435/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001436 * @brief Parse leaf-list element.
1437 *
1438 * @param[in,out] ctx YIN parser context for logging and to store current state.
1439 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1440 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001441 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001442 *
1443 * @return LY_ERR values.
1444 */
1445static LY_ERR
1446yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1447 struct tree_node_meta *node_meta)
1448{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001449 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001450
David Sedlákbf8a2b72019-08-14 16:48:10 +02001451 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, llist, next);
David Sedlák8d552d62019-08-06 15:29:05 +02001452
David Sedlákc3da3ef2019-07-19 12:56:08 +02001453 llist->nodetype = LYS_LEAFLIST;
1454 llist->parent = node_meta->parent;
1455
David Sedlákc3da3ef2019-07-19 12:56:08 +02001456 /* parse argument */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001457 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, YANG_LEAF_LIST));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001458
1459 /* parse content */
1460 struct yin_subelement subelems[14] = {
1461 {YANG_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1462 {YANG_DEFAULT, &llist->dflts, 0},
1463 {YANG_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1464 {YANG_IF_FEATURE, &llist->iffeatures, 0},
1465 {YANG_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1466 {YANG_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1467 {YANG_MUST, &llist->musts, 0},
1468 {YANG_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1469 {YANG_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1470 {YANG_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1471 {YANG_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1472 {YANG_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1473 {YANG_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1474 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001475 };
David Sedlákc3da3ef2019-07-19 12:56:08 +02001476 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, YANG_LEAF_LIST, NULL, &llist->exts));
1477
David Sedlákbf8a2b72019-08-14 16:48:10 +02001478 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001479 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001480 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001481 return LY_EVALID;
1482 }
1483 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001484 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001485 return LY_EVALID;
1486 }
1487
1488 return LY_SUCCESS;
1489}
1490
1491/**
David Sedlák04e17b22019-07-19 15:29:48 +02001492 * @brief Parse typedef element.
1493 *
1494 * @param[in,out] ctx YIN parser context for logging and to store current state.
1495 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1496 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001497 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001498 *
1499 * @return LY_ERR values.
1500 */
1501static LY_ERR
1502yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02001503 struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001504{
1505 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001506 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
David Sedlák6881b512019-08-13 12:52:00 +02001507 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001508
1509 /* parse argument */
1510 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, YANG_TYPEDEF));
1511
1512 /* parse content */
1513 struct yin_subelement subelems[7] = {
1514 {YANG_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1515 {YANG_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1516 {YANG_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1517 {YANG_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1518 {YANG_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1519 {YANG_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1520 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001521 };
David Sedlák04e17b22019-07-19 15:29:48 +02001522 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, YANG_TYPEDEF, NULL, &tpdf->exts));
1523
1524 /* store data for collision check */
1525 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
David Sedláke8b74df2019-08-14 14:18:22 +02001526 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0) == -1, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001527 }
1528
1529 return LY_SUCCESS;
1530}
1531
1532/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001533 * @brief Parse refine element.
1534 *
1535 * @param[in,out] ctx YIN parser context for logging and to store current state.
1536 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1537 * @param[in,out] data Data to read from, always moved to currently handled character.
1538 * @param[in,out] refines Refines to add to.
1539 *
1540 * @return LY_ERR values.
1541 */
1542static LY_ERR
1543yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1544 struct lysp_refine **refines)
1545{
1546 struct lysp_refine *rf;
1547
1548 /* allocate new refine */
1549 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1550
1551 /* parse attribute */
1552 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, YANG_REFINE));
1553 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1554
1555 /* parse content */
1556 struct yin_subelement subelems[11] = {
1557 {YANG_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1558 {YANG_DEFAULT, &rf->dflts, 0},
1559 {YANG_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1560 {YANG_IF_FEATURE, &rf->iffeatures, 0},
1561 {YANG_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1562 {YANG_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1563 {YANG_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1564 {YANG_MUST, &rf->musts, 0},
1565 {YANG_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1566 {YANG_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1567 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001568 };
David Sedlákd2d676a2019-07-22 11:28:19 +02001569 return yin_parse_content(ctx, subelems, 11, data, YANG_REFINE, NULL, &rf->exts);
1570}
1571
1572/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001573 * @brief Parse uses element.
1574 *
1575 * @param[in,out] ctx YIN parser context for logging and to store current state.
1576 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1577 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001578 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001579 *
1580 * @return LY_ERR values.
1581 */
1582static LY_ERR
1583yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1584 struct tree_node_meta *node_meta)
1585{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001586 struct lysp_node_uses *uses;
1587
David Sedlák8d552d62019-08-06 15:29:05 +02001588 /* create new uses */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001589 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, uses, next);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001590 uses->nodetype = LYS_USES;
1591 uses->parent = node_meta->parent;
1592
David Sedlák0d6de5a2019-07-22 13:25:44 +02001593 /* parse argument */
1594 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, YANG_USES));
1595
1596 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001597 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001598 struct yin_subelement subelems[8] = {
1599 {YANG_AUGMENT, &augments, 0},
1600 {YANG_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1601 {YANG_IF_FEATURE, &uses->iffeatures, 0},
1602 {YANG_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1603 {YANG_REFINE, &uses->refines, 0},
1604 {YANG_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1605 {YANG_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1606 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001607 };
David Sedlák0d6de5a2019-07-22 13:25:44 +02001608 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, YANG_USES, NULL, &uses->exts));
1609 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1610
1611 return LY_SUCCESS;
1612}
1613
1614/**
David Sedlákaa854b02019-07-22 14:17:10 +02001615 * @brief Parse revision element.
1616 *
1617 * @param[in,out] ctx YIN parser context for logging and to store current state.
1618 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1619 * @param[in,out] data Data to read from, always moved to currently handled character.
1620 * @param[in,out] revs Parsed revisions to add to.
1621 *
1622 * @return LY_ERR values.
1623 */
1624static LY_ERR
1625yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1626 struct lysp_revision **revs)
1627{
1628 struct lysp_revision *rev;
1629 const char *temp_date = NULL;
1630
1631 /* allocate new reivison */
1632 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1633
1634 /* parse argument */
1635 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, YANG_REVISION));
1636 /* check value */
1637 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1638 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1639 return LY_EVALID;
1640 }
1641 strcpy(rev->date, temp_date);
1642 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1643
1644 /* parse content */
1645 struct yin_subelement subelems[3] = {
1646 {YANG_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1647 {YANG_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1648 {YANG_CUSTOM, NULL, 0},
1649 };
1650 return yin_parse_content(ctx, subelems, 3, data, YANG_REVISION, NULL, &rev->exts);
1651}
1652
David Sedlák5e13dea2019-07-22 16:06:45 +02001653/**
1654 * @brief Parse include element.
1655 *
1656 * @param[in,out] ctx YIN parser context for logging and to store current state.
1657 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1658 * @param[in,out] data Data to read from, always moved to currently handled character.
1659 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1660 *
1661 * @return LY_ERR values.
1662 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001663static LY_ERR
1664yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1665 struct include_meta *inc_meta)
1666{
1667 struct lysp_include *inc;
1668
1669 /* allocate new include */
1670 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1671
1672 /* parse argument */
1673 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, YANG_INCLUDE));
1674
1675 /* submodules share the namespace with the module names, so there must not be
1676 * a module of the same name in the context, no need for revision matching */
1677 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 +02001678 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001679 return LY_EVALID;
1680 }
1681
1682 /* parse content */
1683 struct yin_subelement subelems[4] = {
1684 {YANG_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1685 {YANG_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1686 {YANG_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1687 {YANG_CUSTOM, NULL, 0},
1688 };
1689 return yin_parse_content(ctx, subelems, 4, data, YANG_INCLUDE, NULL, &inc->exts);
1690}
1691
David Sedlákaa854b02019-07-22 14:17:10 +02001692/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001693 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001694 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001695 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001696 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of revision-date element.
1697 * @param[in,out] data Data to read from, always moved to currently handled character.
1698 * @param[in,out] rev Array to store the parsed value in.
1699 * @param[in,out] exts Extension instances to add to.
1700 *
1701 * @return LY_ERR values.
1702 */
1703static LY_ERR
1704yin_parse_revision_date(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, char *rev,
1705 struct lysp_ext_instance **exts)
1706{
1707 const char *temp_rev;
1708 struct yin_subelement subelems[1] = {
1709 {YANG_CUSTOM, NULL, 0}
1710 };
1711
1712 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, YANG_REVISION_DATE));
1713 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
1714 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
1715
1716 strcpy(rev, temp_rev);
1717 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
1718
1719 return yin_parse_content(ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
1720}
1721
1722/**
1723 * @brief Parse config element.
1724 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001725 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001726 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1727 * @param[in,out] data Data to read from, always moved to currently handled character.
1728 * @param[in,out] flags Flags to add to.
1729 * @param[in,out] exts Extension instances to add to.
1730 *
1731 * @return LY_ERR values.
1732 */
1733static LY_ERR
1734yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1735 struct lysp_ext_instance **exts)
1736{
1737 const char *temp_val = NULL;
1738 struct yin_subelement subelems[1] = {
1739 {YANG_CUSTOM, NULL, 0}
1740 };
1741
1742 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_CONFIG));
1743 if (strcmp(temp_val, "true") == 0) {
1744 *flags |= LYS_CONFIG_W;
1745 } else if (strcmp(temp_val, "false") == 0) {
1746 *flags |= LYS_CONFIG_R;
1747 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001748 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
1749 "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001750 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1751 return LY_EVALID;
1752 }
1753 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1754
1755 return yin_parse_content(ctx, subelems, 1, data, YANG_CONFIG, NULL, exts);
1756}
1757
1758/**
1759 * @brief Parse yang-version element.
1760 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001761 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001762 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yang-version element.
1763 * @param[in] data Data to read from, always moved to currently handled character.
1764 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001765 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001766 *
1767 * @return LY_ERR values.
1768 */
1769static LY_ERR
1770yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
1771 struct lysp_ext_instance **exts)
1772{
1773 const char *temp_version = NULL;
1774 struct yin_subelement subelems[1] = {
1775 {YANG_CUSTOM, NULL, 0}
1776 };
1777
1778 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, YANG_YANG_VERSION));
1779 if (strcmp(temp_version, "1.0") == 0) {
1780 *version = LYS_VERSION_1_0;
1781 } else if (strcmp(temp_version, "1.1") == 0) {
1782 *version = LYS_VERSION_1_1;
1783 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001784 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
1785 "yang-version", "1.0", "1.1");
David Sedlákdfbbb442019-08-06 16:33:21 +02001786 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1787 return LY_EVALID;
1788 }
1789 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1790 ctx->mod_version = *version;
1791
1792 return yin_parse_content(ctx, subelems, 1, data, YANG_YANG_VERSION, NULL, exts);
1793}
1794
1795/**
1796 * @brief Parse import element.
1797 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001798 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001799 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1800 * @param[in,out] data Data to read from, always moved to currently handled character.
1801 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1802 *
1803 * @return LY_ERR values.
1804 */
1805static LY_ERR
1806yin_parse_import(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct import_meta *imp_meta)
1807{
1808 struct lysp_import *imp;
1809 /* allocate new element in sized array for import */
1810 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
1811
1812 struct yin_subelement subelems[5] = {
1813 {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1814 {YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1815 {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1816 {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1817 {YANG_CUSTOM, NULL, 0}
1818 };
1819
1820 /* parse import attributes */
1821 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, YANG_IMPORT));
1822 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
1823 /* check prefix validity */
1824 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1825
1826 return LY_SUCCESS;
1827}
1828
1829/**
1830 * @brief Parse mandatory element.
1831 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001832 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001833 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1834 * @param[in,out] data Data to read from, always moved to currently handled character.
1835 * @param[in,out] flags Flags to add to.
1836 * @param[in,out] exts Extension instances to add to.
1837 *
1838 * @return LY_ERR values.
1839 */
1840static LY_ERR
1841yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1842 struct lysp_ext_instance **exts)
1843{
1844 const char *temp_val = NULL;
1845 struct yin_subelement subelems[1] = {
1846 {YANG_CUSTOM, NULL, 0}
1847 };
1848
1849 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MANDATORY));
1850 if (strcmp(temp_val, "true") == 0) {
1851 *flags |= LYS_MAND_TRUE;
1852 } else if (strcmp(temp_val, "false") == 0) {
1853 *flags |= LYS_MAND_FALSE;
1854 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001855 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1856 "mandatory", "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001857 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1858 return LY_EVALID;
1859 }
1860 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1861
1862 return yin_parse_content(ctx, subelems, 1, data, YANG_MANDATORY, NULL, exts);
1863}
1864
1865/**
1866 * @brief Parse status element.
1867 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001868 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001869 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1870 * @param[in,out] data Data to read from, always moved to currently handled character.
1871 * @param[in,out] flags Flags to add to.
1872 * @param[in,out] exts Extension instances to add to.
1873 *
1874 * @return LY_ERR values.
1875 */
1876static LY_ERR
1877yin_parse_status(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1878 struct lysp_ext_instance **exts)
1879{
1880 const char *value = NULL;
1881 struct yin_subelement subelems[1] = {
1882 {YANG_CUSTOM, NULL, 0}
1883 };
1884
1885 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &value, Y_STR_ARG, YANG_STATUS));
1886 if (strcmp(value, "current") == 0) {
1887 *flags |= LYS_STATUS_CURR;
1888 } else if (strcmp(value, "deprecated") == 0) {
1889 *flags |= LYS_STATUS_DEPRC;
1890 } else if (strcmp(value, "obsolete") == 0) {
1891 *flags |= LYS_STATUS_OBSLT;
1892 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001893 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
1894 "status", "current", "deprecated", "obsolete");
David Sedlákdfbbb442019-08-06 16:33:21 +02001895 FREE_STRING(ctx->xml_ctx.ctx, value);
1896 return LY_EVALID;
1897 }
1898 FREE_STRING(ctx->xml_ctx.ctx, value);
1899
1900 return yin_parse_content(ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
1901}
1902
1903/**
1904 * @brief Parse when element.
1905 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001906 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001907 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of when element.
1908 * @param[in,out] data Data to read from, always moved to currently handled character.
1909 * @param[out] when_p When pointer to parse to.
1910 */
1911static LY_ERR
1912yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
1913{
1914 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001915 LY_ERR ret = LY_SUCCESS;
1916
David Sedlákdfbbb442019-08-06 16:33:21 +02001917 when = calloc(1, sizeof *when);
1918 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedláka56e0012019-08-15 13:21:25 +02001919 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, YANG_WHEN);
1920 LY_CHECK_ERR_RET(ret, free(when), ret);
1921
David Sedlákdfbbb442019-08-06 16:33:21 +02001922 *when_p = when;
1923 struct yin_subelement subelems[3] = {
1924 {YANG_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1925 {YANG_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1926 {YANG_CUSTOM, NULL, 0}
1927 };
1928
1929 return yin_parse_content(ctx, subelems, 3, data, YANG_WHEN, NULL, &when->exts);
1930}
1931
1932/**
1933 * @brief Parse yin-elemenet element.
1934 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001935 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001936 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yin-element element.
1937 * @param[in,out] data Data to read from, always moved to currently handled position.
1938 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001939 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001940 *
1941 * @return LY_ERR values.
1942 */
1943static LY_ERR
1944yin_parse_yin_element_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1945 uint16_t *flags, struct lysp_ext_instance **exts)
1946{
1947 const char *temp_val = NULL;
1948 struct yin_subelement subelems[1] = {
1949 {YANG_CUSTOM, NULL, 0}
1950 };
1951
1952 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_YIN_ELEMENT));
1953 if (strcmp(temp_val, "true") == 0) {
1954 *flags |= LYS_YINELEM_TRUE;
1955 } else if (strcmp(temp_val, "false") == 0) {
1956 *flags |= LYS_YINELEM_FALSE;
1957 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001958 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1959 "yin-element", "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001960 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1961 return LY_EVALID;
1962 }
1963 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1964
1965 return yin_parse_content(ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
1966}
1967
1968/**
1969 * @brief Parse argument element.
1970 *
1971 * @param[in,out] xml_ctx Xml context.
1972 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of argument element.
1973 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001974 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1975 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001976 *
1977 * @return LY_ERR values.
1978 */
1979static LY_ERR
1980yin_parse_argument_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1981 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
1982{
1983 struct yin_subelement subelems[2] = {
1984 {YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1985 {YANG_CUSTOM, NULL, 0}
1986 };
1987
1988 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, YANG_ARGUMENT));
1989
1990 return yin_parse_content(ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
1991}
1992
1993/**
1994 * @brief Parse the extension statement.
1995 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001996 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001997 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension element.
1998 * @param[in,out] data Data to read from.
1999 * @param[in,out] extensions Extensions to add to.
2000 *
2001 * @return LY_ERR values.
2002 */
2003static LY_ERR
2004yin_parse_extension(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_ext **extensions)
2005{
2006 struct lysp_ext *ex;
2007 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
2008 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ex->name, Y_IDENTIF_ARG, YANG_EXTENSION));
2009
2010 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
2011 struct yin_subelement subelems[5] = {
2012 {YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2013 {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2014 {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2015 {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2016 {YANG_CUSTOM, NULL, 0}
2017 };
2018
2019 return yin_parse_content(ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
2020}
2021
2022/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002023 * @brief Parse feature element.
2024 *
2025 * @param[in,out] ctx YIN parser context for logging and to store current state.
2026 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2027 * @param[in,out] data Data to read from, always moved to currently handled character.
2028 * @param[in,out] features Features to add to.
2029 *
2030 * @return LY_ERR values.
2031 */
2032static LY_ERR
2033yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2034 struct lysp_feature **features)
2035{
2036 struct lysp_feature *feat;
2037
2038 /* allocate new feature */
2039 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
2040
2041 /* parse argument */
2042 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, YANG_FEATURE));
2043
2044 /* parse content */
2045 struct yin_subelement subelems[5] = {
2046 {YANG_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2047 {YANG_IF_FEATURE, &feat->iffeatures, 0},
2048 {YANG_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2049 {YANG_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2050 {YANG_CUSTOM, NULL, 0},
2051 };
2052 return yin_parse_content(ctx, subelems, 5, data, YANG_FEATURE, NULL, &feat->exts);
2053}
2054
2055/**
David Sedlák28794f22019-07-22 16:45:00 +02002056 * @brief Parse identity element.
2057 *
2058 * @param[in,out] ctx YIN parser context for logging and to store current state.
2059 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2060 * @param[in,out] data Data to read from, always moved to currently handled character.
2061 * @param[in,out] identities Identities to add to.
2062 *
2063 * @return LY_ERR values.
2064 */
2065static LY_ERR
2066yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2067 struct lysp_ident **identities)
2068{
2069 struct lysp_ident *ident;
2070
2071 /* allocate new identity */
2072 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
2073
2074 /* parse argument */
2075 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, YANG_IDENTITY));
2076
2077 /* parse content */
2078 struct yin_subelement subelems[6] = {
2079 {YANG_BASE, &ident->bases, 0},
2080 {YANG_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2081 {YANG_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2082 {YANG_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2083 {YANG_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2084 {YANG_CUSTOM, NULL, 0},
2085 };
2086 return yin_parse_content(ctx, subelems, 6, data, YANG_IDENTITY, NULL, &ident->exts);
2087}
2088
2089/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002090 * @brief Parse list element.
2091 *
2092 * @param[in,out] ctx YIN parser context for logging and to store current state.
2093 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2094 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002095 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002096 *
2097 * @return LY_ERR values.
2098 */
2099static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02002100yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2101 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002102{
David Sedlákaf536aa2019-07-23 13:42:23 +02002103 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002104 LY_ERR ret = LY_SUCCESS;
2105 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02002106
David Sedlákbf8a2b72019-08-14 16:48:10 +02002107 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, list, next);
David Sedlákaf536aa2019-07-23 13:42:23 +02002108 list->nodetype = LYS_LIST;
2109 list->parent = node_meta->parent;
2110
David Sedlákaf536aa2019-07-23 13:42:23 +02002111 /* parse argument */
2112 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, YANG_LIST));
2113
2114 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02002115 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
2116 YANG_ACTION, &list->actions, 0,
2117 YANG_ANYDATA, &list->child, 0,
2118 YANG_ANYXML, &list->child, 0,
2119 YANG_CHOICE, &list->child, 0,
2120 YANG_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2121 YANG_CONTAINER, &list->child, 0,
2122 YANG_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2123 YANG_GROUPING, &list->groupings, 0,
2124 YANG_IF_FEATURE, &list->iffeatures, 0,
2125 YANG_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2126 YANG_LEAF, &list->child, 0,
2127 YANG_LEAF_LIST, &list->child, 0,
2128 YANG_LIST, &list->child, 0,
2129 YANG_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2130 YANG_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2131 YANG_MUST, &list->musts, 0,
2132 YANG_NOTIFICATION, &list->notifs, 0,
2133 YANG_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2134 YANG_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2135 YANG_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2136 YANG_TYPEDEF, &list->typedefs, 0,
2137 YANG_UNIQUE, &list->uniques, 0,
2138 YANG_USES, &list->child, 0,
2139 YANG_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2140 YANG_CUSTOM, NULL, 0
2141 ));
2142 ret = yin_parse_content(ctx, subelems, 25, data, YANG_LIST, NULL, &list->exts);
2143 subelems_deallocator(25, subelems);
2144 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002145
2146 /* finalize parent pointers to the reallocated items */
2147 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
2148
2149 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02002150 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002151 return LY_EVALID;
2152 }
2153
2154 return LY_SUCCESS;
2155}
2156
2157/**
David Sedlák031b9e72019-07-23 15:19:37 +02002158 * @brief Parse notification element.
2159 *
2160 * @param[in,out] ctx YIN parser context for logging and to store current state.
2161 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2162 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02002163 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002164 *
2165 * @return LY_ERR values.
2166 */
2167static LY_ERR
2168yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002169 struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002170{
2171 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002172 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002173 LY_ERR ret = LY_SUCCESS;
2174 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002175
2176 /* allocate new notification */
David Sedlák6881b512019-08-13 12:52:00 +02002177 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002178 notif->nodetype = LYS_NOTIF;
2179 notif->parent = notif_meta->parent;
2180
2181 /* parse argument */
2182 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, YANG_NOTIFICATION));
2183
2184 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002185 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
2186 YANG_ANYDATA, &notif->data, 0,
2187 YANG_ANYXML, &notif->data, 0,
2188 YANG_CHOICE, &notif->data, 0,
2189 YANG_CONTAINER, &notif->data, 0,
2190 YANG_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2191 YANG_GROUPING, &notif->groupings, 0,
2192 YANG_IF_FEATURE, &notif->iffeatures, 0,
2193 YANG_LEAF, &notif->data, 0,
2194 YANG_LEAF_LIST, &notif->data, 0,
2195 YANG_LIST, &notif->data, 0,
2196 YANG_MUST, &notif->musts, YIN_SUBELEM_VER2,
2197 YANG_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2198 YANG_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2199 YANG_TYPEDEF, &notif->typedefs, 0,
2200 YANG_USES, &notif->data, 0,
2201 YANG_CUSTOM, NULL, 0
2202 ));
2203
2204 ret = yin_parse_content(ctx, subelems, 16, data, YANG_NOTIFICATION, NULL, &notif->exts);
2205 subelems_deallocator(16, subelems);
2206 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002207
2208 /* finalize parent pointers to the reallocated items */
2209 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2210
2211 return LY_SUCCESS;
2212}
2213
2214/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002215 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002216 *
2217 * @param[in,out] ctx YIN parser context for logging and to store current state.
2218 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2219 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002220 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002221 *
2222 * @return LY_ERR values.
2223 */
2224static LY_ERR
2225yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002226 struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002227{
2228 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002229 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002230 LY_ERR ret = LY_SUCCESS;
2231 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002232
2233 /* create new grouping */
David Sedlák6881b512019-08-13 12:52:00 +02002234 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002235 grp->nodetype = LYS_GROUPING;
2236 grp->parent = gr_meta->parent;
2237
2238 /* parse argument */
2239 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, YANG_GROUPING));
2240
2241 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002242 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
2243 YANG_ACTION, &grp->actions, 0,
2244 YANG_ANYDATA, &grp->data, 0,
2245 YANG_ANYXML, &grp->data, 0,
2246 YANG_CHOICE, &grp->data, 0,
2247 YANG_CONTAINER, &grp->data, 0,
2248 YANG_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2249 YANG_GROUPING, &grp->groupings, 0,
2250 YANG_LEAF, &grp->data, 0,
2251 YANG_LEAF_LIST, &grp->data, 0,
2252 YANG_LIST, &grp->data, 0,
2253 YANG_NOTIFICATION, &grp->notifs, 0,
2254 YANG_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2255 YANG_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2256 YANG_TYPEDEF, &grp->typedefs, 0,
2257 YANG_USES, &grp->data, 0,
2258 YANG_CUSTOM, NULL, 0
2259 ));
2260 ret = yin_parse_content(ctx, subelems, 16, data, YANG_GROUPING, NULL, &grp->exts);
2261 subelems_deallocator(16, subelems);
2262 LY_CHECK_RET(ret);
2263
David Sedláke3ce9ef2019-07-23 16:34:30 +02002264 /* finalize parent pointers to the reallocated items */
2265 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2266
2267 return LY_SUCCESS;
2268}
2269
2270/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002271 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002272 *
2273 * @param[in,out] ctx YIN parser context for logging and to store current state.
2274 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2275 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002276 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002277 *
2278 * @return LY_ERR values.
2279 */
2280static LY_ERR
2281yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2282 struct tree_node_meta *node_meta)
2283{
David Sedlákf111bcb2019-07-23 17:15:51 +02002284 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002285 LY_ERR ret = LY_SUCCESS;
2286 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002287
2288 /* create new container */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002289 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, cont, next);
David Sedlákf111bcb2019-07-23 17:15:51 +02002290 cont->nodetype = LYS_CONTAINER;
2291 cont->parent = node_meta->parent;
2292
David Sedlákf111bcb2019-07-23 17:15:51 +02002293 /* parse aegument */
2294 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, YANG_CONTAINER));
2295
2296 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002297 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
2298 YANG_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2299 YANG_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2300 YANG_ANYXML, &cont->child, 0,
2301 YANG_CHOICE, &cont->child, 0,
2302 YANG_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2303 YANG_CONTAINER, &cont->child, 0,
2304 YANG_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2305 YANG_GROUPING, &cont->groupings, 0,
2306 YANG_IF_FEATURE, &cont->iffeatures, 0,
2307 YANG_LEAF, &cont->child, 0,
2308 YANG_LEAF_LIST, &cont->child, 0,
2309 YANG_LIST, &cont->child, 0,
2310 YANG_MUST, &cont->musts, 0,
2311 YANG_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2312 YANG_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2313 YANG_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2314 YANG_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2315 YANG_TYPEDEF, &cont->typedefs, 0,
2316 YANG_USES, &cont->child, 0,
2317 YANG_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2318 YANG_CUSTOM, NULL, 0
2319 ));
2320 ret = yin_parse_content(ctx, subelems, 21, data, YANG_CONTAINER, NULL, &cont->exts);
2321 subelems_deallocator(21, subelems);
2322 LY_CHECK_RET(ret);
2323
David Sedlákf111bcb2019-07-23 17:15:51 +02002324 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2325
2326 return LY_SUCCESS;
2327}
2328
2329/**
David Sedlák5379d392019-07-24 10:42:03 +02002330 * @brief Parse case element.
2331 *
2332 * @param[in,out] ctx YIN parser context for logging and to store current state.
2333 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2334 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002335 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002336 *
2337 * @return LY_ERR values.
2338 */
2339static LY_ERR
2340yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2341 struct tree_node_meta *node_meta)
2342{
David Sedlák5379d392019-07-24 10:42:03 +02002343 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002344 LY_ERR ret = LY_SUCCESS;
2345 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002346
2347 /* create new case */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002348 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, cas, next);
David Sedlák5379d392019-07-24 10:42:03 +02002349 cas->nodetype = LYS_CASE;
2350 cas->parent = node_meta->parent;
2351
David Sedlák5379d392019-07-24 10:42:03 +02002352 /* parse argument */
2353 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, YANG_CASE));
2354
2355 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002356 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
2357 YANG_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2358 YANG_ANYXML, &cas->child, 0,
2359 YANG_CHOICE, &cas->child, 0,
2360 YANG_CONTAINER, &cas->child, 0,
2361 YANG_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2362 YANG_IF_FEATURE, &cas->iffeatures, 0,
2363 YANG_LEAF, &cas->child, 0,
2364 YANG_LEAF_LIST, &cas->child, 0,
2365 YANG_LIST, &cas->child, 0,
2366 YANG_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2367 YANG_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2368 YANG_USES, &cas->child, 0,
2369 YANG_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2370 YANG_CUSTOM, NULL, 0
2371 ));
2372 ret = yin_parse_content(ctx, subelems, 14, data, YANG_CASE, NULL, &cas->exts);
2373 subelems_deallocator(14, subelems);
2374
2375 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002376}
2377
2378/**
David Sedlák05404f62019-07-24 14:11:53 +02002379 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002380 *
2381 * @param[in,out] ctx YIN parser context for logging and to store current state.
2382 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2383 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002384 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002385 *
2386 * @return LY_ERR values.
2387 */
2388LY_ERR
2389yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2390 struct tree_node_meta *node_meta)
2391{
David Sedlák81497a32019-08-13 16:56:26 +02002392 LY_ERR ret = LY_SUCCESS;
2393 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002394 struct lysp_node_choice *choice;
2395
2396 /* create new choice */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002397 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, choice, next);
David Sedlák8d552d62019-08-06 15:29:05 +02002398
David Sedlákb7abcfa2019-07-24 12:33:35 +02002399 choice->nodetype = LYS_CHOICE;
2400 choice->parent = node_meta->parent;
2401
David Sedlákb7abcfa2019-07-24 12:33:35 +02002402 /* parse argument */
2403 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, YANG_CHOICE));
2404
2405 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002406 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
2407 YANG_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2408 YANG_ANYXML, &choice->child, 0,
2409 YANG_CASE, &choice->child, 0,
2410 YANG_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2411 YANG_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2412 YANG_CONTAINER, &choice->child, 0,
2413 YANG_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2414 YANG_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2415 YANG_IF_FEATURE, &choice->iffeatures, 0,
2416 YANG_LEAF, &choice->child, 0,
2417 YANG_LEAF_LIST, &choice->child, 0,
2418 YANG_LIST, &choice->child, 0,
2419 YANG_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2420 YANG_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2421 YANG_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2422 YANG_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2423 YANG_CUSTOM, NULL, 0
2424 ));
2425 ret = yin_parse_content(ctx, subelems, 17, data, YANG_CHOICE, NULL, &choice->exts);
2426 subelems_deallocator(17, subelems);
2427 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002428}
2429
2430/**
David Sedlák05404f62019-07-24 14:11:53 +02002431 * @brief Parse input or output element.
2432 *
2433 * @param[in,out] ctx YIN parser context for logging and to store current state.
2434 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2435 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002436 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002437 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2438 *
2439 * @return LY_ERR values.
2440 */
2441static LY_ERR
2442yin_parse_inout(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword inout_kw,
2443 struct inout_meta *inout_meta)
2444{
David Sedlák81497a32019-08-13 16:56:26 +02002445 LY_ERR ret = LY_SUCCESS;
2446 struct yin_subelement *subelems = NULL;
2447
David Sedlák05404f62019-07-24 14:11:53 +02002448 /* initiate structure */
2449 inout_meta->inout_p->nodetype = (inout_kw == YANG_INPUT) ? LYS_INPUT : LYS_OUTPUT;
2450 inout_meta->inout_p->parent = inout_meta->parent;
2451
2452 /* check attributes */
2453 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
2454
2455 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002456 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
2457 YANG_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2458 YANG_ANYXML, &inout_meta->inout_p->data, 0,
2459 YANG_CHOICE, &inout_meta->inout_p->data, 0,
2460 YANG_CONTAINER, &inout_meta->inout_p->data, 0,
2461 YANG_GROUPING, &inout_meta->inout_p->groupings, 0,
2462 YANG_LEAF, &inout_meta->inout_p->data, 0,
2463 YANG_LEAF_LIST, &inout_meta->inout_p->data, 0,
2464 YANG_LIST, &inout_meta->inout_p->data, 0,
2465 YANG_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2466 YANG_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2467 YANG_USES, &inout_meta->inout_p->data, 0,
2468 YANG_CUSTOM, NULL, 0
2469 ));
2470 ret = yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts);
2471 subelems_deallocator(12, subelems);
2472 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002473
2474 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002475 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 +02002476
2477 return LY_SUCCESS;
2478}
2479
David Sedlák992fb7c2019-07-24 16:51:01 +02002480/**
2481 * @brief Parse action element.
2482 *
2483 * @param[in,out] ctx YIN parser context for logging and to store current state.
2484 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2485 * @param[in,out] data Data to read from, always moved to currently handled character.
2486 * @param[in] act_meta Meta information about parent node and actions to add to.
2487 *
2488 * @return LY_ERR values.
2489 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002490static LY_ERR
2491yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002492 struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002493{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002494 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002495 LY_ERR ret = LY_SUCCESS;
2496 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002497
2498 /* create new action */
David Sedlák6881b512019-08-13 12:52:00 +02002499 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *acts, act, LY_EMEM);
David Sedlák85d0eca2019-07-24 15:15:21 +02002500 act->nodetype = LYS_ACTION;
2501 act->parent = act_meta->parent;
2502
2503 /* parse argument */
2504 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, YANG_ACTION));
2505
2506 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002507 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
2508 YANG_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2509 YANG_GROUPING, &act->groupings, 0,
2510 YANG_IF_FEATURE, &act->iffeatures, 0,
2511 YANG_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2512 YANG_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2513 YANG_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2514 YANG_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2515 YANG_TYPEDEF, &act->typedefs, 0,
2516 YANG_CUSTOM, NULL, 0
2517 ));
2518 ret = (yin_parse_content(ctx, subelems, 9, data, YANG_ACTION, NULL, &act->exts));
2519 subelems_deallocator(9, subelems);
2520 LY_CHECK_RET(ret);
2521
David Sedlák85d0eca2019-07-24 15:15:21 +02002522 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2523
2524 return LY_SUCCESS;
2525}
2526
David Sedlák05404f62019-07-24 14:11:53 +02002527/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002528 * @brief Parse augment element.
2529 *
2530 * @param[in,out] ctx YIN parser context for logging and to store current state.
2531 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2532 * @param[in,out] data Data to read from, always moved to currently handled character.
2533 * @param[in] aug_meta Meta information about parent node and augments to add to.
2534 *
2535 * @return LY_ERR values.
2536 */
2537static LY_ERR
2538yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002539 struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002540{
2541 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002542 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002543 LY_ERR ret = LY_SUCCESS;
2544 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002545
2546 /* create new augment */
David Sedlák6881b512019-08-13 12:52:00 +02002547 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002548 aug->nodetype = LYS_AUGMENT;
2549 aug->parent = aug_meta->parent;
2550
2551 /* parse argument */
2552 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, YANG_AUGMENT));
2553 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2554
2555 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002556 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
2557 YANG_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2558 YANG_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2559 YANG_ANYXML, &aug->child, 0,
2560 YANG_CASE, &aug->child, 0,
2561 YANG_CHOICE, &aug->child, 0,
2562 YANG_CONTAINER, &aug->child, 0,
2563 YANG_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2564 YANG_IF_FEATURE, &aug->iffeatures, 0,
2565 YANG_LEAF, &aug->child, 0,
2566 YANG_LEAF_LIST, &aug->child, 0,
2567 YANG_LIST, &aug->child, 0,
2568 YANG_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2569 YANG_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2570 YANG_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2571 YANG_USES, &aug->child, 0,
2572 YANG_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2573 YANG_CUSTOM, NULL, 0
2574 ));
2575 ret = yin_parse_content(ctx, subelems, 17, data, YANG_AUGMENT, NULL, &aug->exts);
2576 subelems_deallocator(17, subelems);
2577 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002578
2579 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2580
2581 return LY_SUCCESS;
2582}
2583
David Sedlák8b754462019-07-25 16:22:13 +02002584/**
2585 * @brief Parse deviate element.
2586 *
2587 * @param[in,out] ctx YIN parser context for logging and to store current state.
2588 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2589 * @param[in,out] data Data to read from, always moved to currently handled character.
2590 * @param[in] deviates Deviates to add to.
2591 *
2592 * @return LY_ERR values.
2593 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002594static LY_ERR
2595yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2596 struct lysp_deviate **deviates)
2597{
2598 LY_ERR ret = LY_SUCCESS;
2599 uint8_t dev_mod;
2600 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002601 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002602 struct lysp_deviate_add *d_add = NULL;
2603 struct lysp_deviate_rpl *d_rpl = NULL;
2604 struct lysp_deviate_del *d_del = NULL;
2605
2606 /* parse argument */
2607 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_DEVIATE));
2608
2609 if (strcmp(temp_val, "not-supported") == 0) {
2610 dev_mod = LYS_DEV_NOT_SUPPORTED;
2611 } else if (strcmp(temp_val, "add") == 0) {
2612 dev_mod = LYS_DEV_ADD;
2613 } else if (strcmp(temp_val, "replace") == 0) {
2614 dev_mod = LYS_DEV_REPLACE;
2615 } else if (strcmp(temp_val, "delete") == 0) {
2616 dev_mod = LYS_DEV_DELETE;
2617 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002618 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
2619 "not-supported", "add", "replace", "delete");
David Sedlák4ffcec82019-07-25 15:10:21 +02002620 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2621 return LY_EVALID;
2622 }
2623 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2624
2625 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2626 d = calloc(1, sizeof *d);
2627 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2628 struct yin_subelement subelems[1] = {
2629 {YANG_CUSTOM, NULL, 0}
2630 };
2631 ret = yin_parse_content(ctx, subelems, 1, data, YANG_DEVIATE, NULL, &d->exts);
2632
2633 } else if (dev_mod == LYS_DEV_ADD) {
2634 d_add = calloc(1, sizeof *d_add);
2635 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2636 d = (struct lysp_deviate *)d_add;
2637 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2638 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2639 struct yin_subelement subelems[9] = {
2640 {YANG_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2641 {YANG_DEFAULT, &d_add->dflts, 0},
2642 {YANG_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2643 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2644 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2645 {YANG_MUST, &d_add->musts, 0},
2646 {YANG_UNIQUE, &d_add->uniques, 0},
2647 {YANG_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2648 {YANG_CUSTOM, NULL, 0},
2649 };
2650 ret = yin_parse_content(ctx, subelems, 9, data, YANG_DEVIATE, NULL, &d_add->exts);
2651
2652 } else if (dev_mod == LYS_DEV_REPLACE) {
2653 d_rpl = calloc(1, sizeof *d_rpl);
2654 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2655 d = (struct lysp_deviate *)d_rpl;
2656 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2657 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2658 struct yin_subelement subelems[8] = {
2659 {YANG_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2660 {YANG_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2661 {YANG_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2662 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2663 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2664 {YANG_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2665 {YANG_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2666 {YANG_CUSTOM, NULL, 0},
2667 };
2668 ret = yin_parse_content(ctx, subelems, 8, data, YANG_DEVIATE, NULL, &d_rpl->exts);
2669
2670 } else {
2671 d_del = calloc(1, sizeof *d_del);
2672 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2673 d = (struct lysp_deviate *)d_del;
2674 struct yin_subelement subelems[5] = {
2675 {YANG_DEFAULT, &d_del->dflts, 0},
2676 {YANG_MUST, &d_del->musts, 0},
2677 {YANG_UNIQUE, &d_del->uniques, 0},
2678 {YANG_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2679 {YANG_CUSTOM, NULL, 0},
2680 };
2681 ret = yin_parse_content(ctx, subelems, 5, data, YANG_DEVIATE, NULL, &d_del->exts);
2682 }
2683 LY_CHECK_GOTO(ret, cleanup);
2684
2685 d->mod = dev_mod;
2686 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002687 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002688
2689 return ret;
2690
2691cleanup:
2692 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002693 return ret;
2694}
2695
David Sedlák992fb7c2019-07-24 16:51:01 +02002696/**
David Sedlák8b754462019-07-25 16:22:13 +02002697 * @brief Parse deviation element.
2698 *
2699 * @param[in,out] ctx YIN parser context for logging and to store current state.
2700 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2701 * @param[in,out] data Data to read from, always moved to currently handled character.
2702 * @param[in] deviations Deviations to add to.
2703 *
2704 * @return LY_ERR values.
2705 */
2706static LY_ERR
2707yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2708 struct lysp_deviation **deviations)
2709{
2710 struct lysp_deviation *dev;
2711
2712 /* create new deviation */
2713 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2714
2715 /* parse argument */
David Sedlák1538a842019-08-08 15:38:51 +02002716 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, YANG_DEVIATION));
David Sedlák8b754462019-07-25 16:22:13 +02002717 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2718 struct yin_subelement subelems[4] = {
2719 {YANG_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2720 {YANG_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2721 {YANG_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2722 {YANG_CUSTOM, NULL, 0},
2723 };
David Sedlák1538a842019-08-08 15:38:51 +02002724 return yin_parse_content(ctx, subelems, 4, data, YANG_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002725}
2726
2727/**
David Sedlákb4e44562019-07-04 15:42:12 +02002728 * @brief Map keyword type to substatement info.
2729 *
2730 * @param[in] kw Keyword type.
2731 *
2732 * @return correct LYEXT_SUBSTMT information.
2733 */
2734static LYEXT_SUBSTMT
2735kw2lyext_substmt(enum yang_keyword kw)
2736{
2737 switch (kw) {
2738 case YANG_ARGUMENT:
2739 return LYEXT_SUBSTMT_ARGUMENT;
2740 case YANG_BASE:
2741 return LYEXT_SUBSTMT_BASE;
2742 case YANG_BELONGS_TO:
2743 return LYEXT_SUBSTMT_BELONGSTO;
2744 case YANG_CONTACT:
2745 return LYEXT_SUBSTMT_CONTACT;
2746 case YANG_DEFAULT:
2747 return LYEXT_SUBSTMT_DEFAULT;
2748 case YANG_DESCRIPTION:
2749 return LYEXT_SUBSTMT_DESCRIPTION;
2750 case YANG_ERROR_APP_TAG:
2751 return LYEXT_SUBSTMT_ERRTAG;
2752 case YANG_ERROR_MESSAGE:
2753 return LYEXT_SUBSTMT_ERRMSG;
2754 case YANG_KEY:
2755 return LYEXT_SUBSTMT_KEY;
2756 case YANG_NAMESPACE:
2757 return LYEXT_SUBSTMT_NAMESPACE;
2758 case YANG_ORGANIZATION:
2759 return LYEXT_SUBSTMT_ORGANIZATION;
2760 case YANG_PATH:
2761 return LYEXT_SUBSTMT_PATH;
2762 case YANG_PREFIX:
2763 return LYEXT_SUBSTMT_PREFIX;
2764 case YANG_PRESENCE:
2765 return LYEXT_SUBSTMT_PRESENCE;
2766 case YANG_REFERENCE:
2767 return LYEXT_SUBSTMT_REFERENCE;
2768 case YANG_REVISION_DATE:
2769 return LYEXT_SUBSTMT_REVISIONDATE;
2770 case YANG_UNITS:
2771 return LYEXT_SUBSTMT_UNITS;
2772 case YANG_VALUE:
2773 return LYEXT_SUBSTMT_VALUE;
2774 case YANG_YANG_VERSION:
2775 return LYEXT_SUBSTMT_VERSION;
2776 case YANG_MODIFIER:
2777 return LYEXT_SUBSTMT_MODIFIER;
2778 case YANG_REQUIRE_INSTANCE:
2779 return LYEXT_SUBSTMT_REQINSTANCE;
2780 case YANG_YIN_ELEMENT:
2781 return LYEXT_SUBSTMT_YINELEM;
2782 case YANG_CONFIG:
2783 return LYEXT_SUBSTMT_CONFIG;
2784 case YANG_MANDATORY:
2785 return LYEXT_SUBSTMT_MANDATORY;
2786 case YANG_ORDERED_BY:
2787 return LYEXT_SUBSTMT_ORDEREDBY;
2788 case YANG_STATUS:
2789 return LYEXT_SUBSTMT_STATUS;
2790 case YANG_FRACTION_DIGITS:
2791 return LYEXT_SUBSTMT_FRACDIGITS;
2792 case YANG_MAX_ELEMENTS:
2793 return LYEXT_SUBSTMT_MAX;
2794 case YANG_MIN_ELEMENTS:
2795 return LYEXT_SUBSTMT_MIN;
2796 case YANG_POSITION:
2797 return LYEXT_SUBSTMT_POSITION;
2798 case YANG_UNIQUE:
2799 return LYEXT_SUBSTMT_UNIQUE;
2800 case YANG_IF_FEATURE:
2801 return LYEXT_SUBSTMT_IFFEATURE;
2802 default:
2803 return LYEXT_SUBSTMT_SELF;
2804 }
2805}
2806
David Sedlákc5b20842019-08-13 10:18:31 +02002807/**
2808 * @brief map keyword to keyword-group.
2809 *
2810 * @param[in] ctx YIN parser context used for logging.
2811 * @param[in] kw Keyword that is child of module or submodule.
2812 * @param[out] group Group of keyword.
2813 *
2814 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2815 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002816static LY_ERR
2817kw2kw_group(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_module_stmt *group)
2818{
2819 switch (kw) {
2820 /* module header */
2821 case YANG_NONE:
2822 case YANG_NAMESPACE:
2823 case YANG_PREFIX:
2824 case YANG_BELONGS_TO:
2825 case YANG_YANG_VERSION:
2826 *group = Y_MOD_MODULE_HEADER;
2827 break;
2828 /* linkage */
2829 case YANG_INCLUDE:
2830 case YANG_IMPORT:
2831 *group = Y_MOD_LINKAGE;
2832 break;
2833 /* meta */
2834 case YANG_ORGANIZATION:
2835 case YANG_CONTACT:
2836 case YANG_DESCRIPTION:
2837 case YANG_REFERENCE:
2838 *group = Y_MOD_META;
2839 break;
2840 /* revision */
2841 case YANG_REVISION:
2842 *group = Y_MOD_REVISION;
2843 break;
2844 /* body */
2845 case YANG_ANYDATA:
2846 case YANG_ANYXML:
2847 case YANG_AUGMENT:
2848 case YANG_CHOICE:
2849 case YANG_CONTAINER:
2850 case YANG_DEVIATION:
2851 case YANG_EXTENSION:
2852 case YANG_FEATURE:
2853 case YANG_GROUPING:
2854 case YANG_IDENTITY:
2855 case YANG_LEAF:
2856 case YANG_LEAF_LIST:
2857 case YANG_LIST:
2858 case YANG_NOTIFICATION:
2859 case YANG_RPC:
2860 case YANG_TYPEDEF:
2861 case YANG_USES:
2862 case YANG_CUSTOM:
2863 *group = Y_MOD_BODY;
2864 break;
2865 default:
2866 LOGINT(ctx->xml_ctx.ctx);
2867 return LY_EINT;
2868 }
2869
2870 return LY_SUCCESS;
2871}
2872
David Sedlákc5b20842019-08-13 10:18:31 +02002873/**
2874 * @brief Check if relative order of two keywords is valid.
2875 *
2876 * @param[in] ctx YIN parser context used for logging.
2877 * @param[in] kw Current keyword.
2878 * @param[in] next_kw Next keyword.
2879 * @param[in] parrent Identification of parrent element, can be se to to YANG_MODULE of YANG_SUBMODULE,
2880 * because relative order is required only in module and submodule sub-elements, used for logging.
2881 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002882 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002883 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002884static LY_ERR
2885yin_check_relative_order(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_keyword next_kw, enum yang_keyword parrent)
2886{
2887 assert(parrent == YANG_MODULE || parrent == YANG_SUBMODULE);
2888 enum yang_module_stmt gr, next_gr;
2889
2890 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2891 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2892
2893 if (gr > next_gr) {
2894 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2895 return LY_EVALID;
2896 }
2897
2898 return LY_SUCCESS;
2899}
2900
David Sedlákd6e56892019-07-01 15:40:24 +02002901LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002902yin_parse_content(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info, signed char subelem_info_size,
David Sedlák3ffbc522019-07-02 17:49:28 +02002903 const char **data, enum yang_keyword current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02002904{
2905 LY_ERR ret = LY_SUCCESS;
David Sedlák8e7bda82019-07-16 17:57:50 +02002906 char *out = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +02002907 const char *prefix, *name;
2908 size_t out_len = 0, prefix_len, name_len;
David Sedlák8e7bda82019-07-16 17:57:50 +02002909 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002910 struct yin_arg_record *attrs = NULL;
David Sedláke6cd89e2019-08-07 12:46:02 +02002911 enum yang_keyword kw = YANG_NONE, last_kw = YANG_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002912 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002913
David Sedlákb0faad82019-07-04 14:28:59 +02002914 assert(is_ordered(subelem_info, subelem_info_size));
David Sedlákd6e56892019-07-01 15:40:24 +02002915
David Sedlákda8ffa32019-07-08 14:17:10 +02002916 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2917 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002918 /* current element has subelements as content */
2919 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002920 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákc5b20842019-08-13 10:18:31 +02002921 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákd6e56892019-07-01 15:40:24 +02002922 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +02002923 if (!name) {
David Sedlákd6e56892019-07-01 15:40:24 +02002924 /* end of current element reached */
2925 break;
2926 }
David Sedlák1af868e2019-07-17 17:03:14 +02002927 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002928 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6cd89e2019-08-07 12:46:02 +02002929 last_kw = kw;
David Sedlákc5b20842019-08-13 10:18:31 +02002930 kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002931
2932 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002933 subelem = get_record(kw, subelem_info_size, subelem_info);
2934 if (!subelem) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002935 if (current_element == YANG_DEVIATE && isdevsub(kw)) {
2936 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2937 } else {
David Sedlákc5b20842019-08-13 10:18:31 +02002938 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 +02002939 }
David Sedlákd6e56892019-07-01 15:40:24 +02002940 ret = LY_EVALID;
2941 goto cleanup;
2942 }
2943
David Sedlák6542aed2019-08-14 10:47:43 +02002944 /* relative order is required only in module and submodule sub-elements */
David Sedláke6cd89e2019-08-07 12:46:02 +02002945 if (current_element == YANG_MODULE || current_element == YANG_SUBMODULE) {
2946 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2947 LY_CHECK_GOTO(ret, cleanup);
2948 }
David Sedlák5f8191e2019-07-08 16:35:52 +02002949
David Sedlák4ffcec82019-07-25 15:10:21 +02002950 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002951 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002952 /* subelement uniquenes */
David Sedlák1538a842019-08-08 15:38:51 +02002953 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 +02002954 return LY_EVALID;
2955 }
David Sedlák1af868e2019-07-17 17:03:14 +02002956 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002957 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002958 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002959 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002960 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002961 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002962 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002963 if (ctx->mod_version < 2) {
David Sedlák1538a842019-08-08 15:38:51 +02002964 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 +02002965 ret = LY_EVALID;
2966 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002967 }
2968 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002969 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002970 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002971
David Sedlákd6e56892019-07-01 15:40:24 +02002972 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002973 /* call responsible function */
David Sedlákd6e56892019-07-01 15:40:24 +02002974 case YANG_CUSTOM:
David Sedlákc5b20842019-08-13 10:18:31 +02002975 ret = yin_parse_extension_instance(ctx, attrs, data, name2fullname(name, prefix_len),
2976 namelen2fulllen(name_len, prefix_len),
David Sedlák1af868e2019-07-17 17:03:14 +02002977 kw2lyext_substmt(current_element),
2978 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002979 break;
2980 case YANG_ACTION:
David Sedlákeaa45792019-07-24 15:25:01 +02002981 case YANG_RPC:
David Sedlák6881b512019-08-13 12:52:00 +02002982 ret = yin_parse_action(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002983 break;
2984 case YANG_ANYDATA:
David Sedlákd6e56892019-07-01 15:40:24 +02002985 case YANG_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002986 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002987 break;
2988 case YANG_ARGUMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002989 ret = yin_parse_argument_element(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002990 break;
2991 case YANG_AUGMENT:
David Sedlák6881b512019-08-13 12:52:00 +02002992 ret = yin_parse_augment(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002993 break;
2994 case YANG_BASE:
David Sedlák6542aed2019-08-14 10:47:43 +02002995 ret = yin_parse_base(ctx, attrs, data, current_element, subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002996 break;
2997 case YANG_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002998 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002999 break;
3000 case YANG_BIT:
David Sedlák43801c92019-08-05 15:58:54 +02003001 ret = yin_parse_bit(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003002 break;
3003 case YANG_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02003004 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003005 break;
3006 case YANG_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02003007 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003008 break;
3009 case YANG_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02003010 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003011 break;
3012 case YANG_CONTACT:
David Sedlák619db942019-07-03 14:47:30 +02003013 case YANG_DESCRIPTION:
3014 case YANG_ORGANIZATION:
3015 case YANG_REFERENCE:
David Sedlákdf2a9732019-08-07 13:23:16 +02003016 ret = yin_parse_meta_element(ctx, attrs, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003017 break;
3018 case YANG_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02003019 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003020 break;
3021 case YANG_DEFAULT:
David Sedlák6542aed2019-08-14 10:47:43 +02003022 case YANG_ERROR_APP_TAG:
3023 case YANG_KEY:
3024 case YANG_PRESENCE:
3025 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 +02003026 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003027 case YANG_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02003028 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003029 break;
3030 case YANG_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02003031 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003032 break;
David Sedlák43801c92019-08-05 15:58:54 +02003033 case YANG_ENUM:
3034 ret = yin_parse_enum(ctx, attrs, data, (struct lysp_type *)subelem->dest);
3035 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003036 case YANG_ERROR_MESSAGE:
David Sedlákdf2a9732019-08-07 13:23:16 +02003037 ret = yin_parse_err_msg_element(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003038 break;
3039 case YANG_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003040 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003041 break;
3042 case YANG_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02003043 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003044 break;
3045 case YANG_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02003046 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003047 break;
3048 case YANG_GROUPING:
David Sedlák6881b512019-08-13 12:52:00 +02003049 ret = yin_parse_grouping(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003050 break;
3051 case YANG_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02003052 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003053 break;
3054 case YANG_IF_FEATURE:
David Sedlák6542aed2019-08-14 10:47:43 +02003055 case YANG_UNITS:
3056 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 +02003057 break;
3058 case YANG_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02003059 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003060 break;
3061 case YANG_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02003062 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003063 break;
3064 case YANG_INPUT:
David Sedlák05404f62019-07-24 14:11:53 +02003065 case YANG_OUTPUT:
3066 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003067 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003068 case YANG_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02003069 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003070 break;
3071 case YANG_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02003072 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003073 break;
3074 case YANG_LENGTH:
David Sedlák6542aed2019-08-14 10:47:43 +02003075 ret = yin_parse_length(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003076 break;
3077 case YANG_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02003078 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003079 break;
3080 case YANG_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02003081 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003082 break;
3083 case YANG_MAX_ELEMENTS:
David Sedlákd6e56892019-07-01 15:40:24 +02003084 case YANG_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02003085 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003086 break;
3087 case YANG_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02003088 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003089 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003090 case YANG_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02003091 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003092 break;
3093 case YANG_NAMESPACE:
David Sedlák6542aed2019-08-14 10:47:43 +02003094 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 +02003095 break;
3096 case YANG_NOTIFICATION:
David Sedlák6881b512019-08-13 12:52:00 +02003097 ret = yin_parse_notification(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003098 break;
3099 case YANG_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02003100 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003101 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003102 case YANG_PATH:
David Sedlák6542aed2019-08-14 10:47:43 +02003103 ret = yin_parse_path(ctx, attrs, data, kw, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003104 break;
3105 case YANG_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02003106 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003107 break;
David Sedlák5545f5d2019-07-11 11:55:16 +02003108 case YANG_VALUE:
David Sedlákd6e56892019-07-01 15:40:24 +02003109 case YANG_POSITION:
David Sedlák6542aed2019-08-14 10:47:43 +02003110 ret = yin_parse_value_pos_element(ctx, attrs, data, kw, (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003111 break;
3112 case YANG_PREFIX:
David Sedlák6542aed2019-08-14 10:47:43 +02003113 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 +02003114 break;
3115 case YANG_RANGE:
David Sedlák6542aed2019-08-14 10:47:43 +02003116 ret = yin_parse_range(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003117 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003118 case YANG_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02003119 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003120 break;
3121 case YANG_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02003122 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003123 break;
3124 case YANG_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02003125 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003126 break;
3127 case YANG_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02003128 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003129 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003130 case YANG_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02003131 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003132 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003133 case YANG_TYPE:
David Sedlák6542aed2019-08-14 10:47:43 +02003134 ret = yin_parse_type(ctx, attrs, data, current_element, subelem);
David Sedlákd6e56892019-07-01 15:40:24 +02003135 break;
3136 case YANG_TYPEDEF:
David Sedlák6881b512019-08-13 12:52:00 +02003137 ret = yin_parse_typedef(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003138 break;
3139 case YANG_UNIQUE:
David Sedlák6542aed2019-08-14 10:47:43 +02003140 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 +02003141 break;
3142 case YANG_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02003143 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003144 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003145 case YANG_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02003146 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003147 break;
3148 case YANG_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003149 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003150 break;
3151 case YANG_YIN_ELEMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02003152 ret = yin_parse_yin_element_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02003153 break;
3154 case YIN_TEXT:
David Sedlák3ffbc522019-07-02 17:49:28 +02003155 case YIN_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02003156 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02003157 break;
3158 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02003159 LOGINT(ctx->xml_ctx.ctx);
David Sedlákbf8a2b72019-08-14 16:48:10 +02003160 ret = LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02003161 }
David Sedlák3ffbc522019-07-02 17:49:28 +02003162 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02003163 FREE_ARRAY(ctx, attrs, free_arg_rec);
3164 attrs = NULL;
3165 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02003166 }
3167 } else {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003168 LY_CHECK_RET(ret);
David Sedlákd6e56892019-07-01 15:40:24 +02003169 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02003170 /* save text content, if text_content isn't set, it's just ignored */
David Sedlákc5b20842019-08-13 10:18:31 +02003171 /* no resources are allocated in this branch, no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02003172 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02003173 if (text_content) {
3174 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003175 *text_content = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák3ffbc522019-07-02 17:49:28 +02003176 if (!*text_content) {
3177 free(out);
3178 return LY_EMEM;
3179 }
3180 } else {
3181 if (out_len == 0) {
David Sedlák99295322019-07-17 11:34:18 +02003182 *text_content = lydict_insert(ctx->xml_ctx.ctx, "", 0);
David Sedlák3ffbc522019-07-02 17:49:28 +02003183 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003184 *text_content = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák3ffbc522019-07-02 17:49:28 +02003185 }
3186 }
3187 }
David Sedlákd6e56892019-07-01 15:40:24 +02003188 /* load closing element */
David Sedlákc5b20842019-08-13 10:18:31 +02003189 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákd6e56892019-07-01 15:40:24 +02003190 }
3191 }
David Sedlák8b754462019-07-25 16:22:13 +02003192 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3193 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003194
3195cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02003196 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02003197 return ret;
3198}
3199
David Sedlák619db942019-07-03 14:47:30 +02003200LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02003201yin_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 +02003202 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003203{
3204 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003205 char *out;
3206 const char *name, *prefix;
3207 size_t out_len, prefix_len, name_len;
3208 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003209 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003210 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
3211 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003212
David Sedlákda8ffa32019-07-08 14:17:10 +02003213 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003214
3215 e->yin = 0;
3216 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02003217 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02003218 e->insubstmt = subelem;
3219 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003220 e->yin |= LYS_YIN;
3221
David Sedlákb1a78352019-06-28 16:16:29 +02003222 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02003223 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02003224 if (!iter->prefix) {
3225 new_subelem = calloc(1, sizeof(*new_subelem));
3226 if (!e->child) {
3227 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003228 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003229 last_subelem->next = new_subelem;
3230 }
3231 last_subelem = new_subelem;
3232
3233 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003234 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
3235 LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003236 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003237 last_subelem->arg = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
David Sedlákb1a78352019-06-28 16:16:29 +02003238 } else {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003239 if (iter->content_len == 0) {
3240 last_subelem->arg = lydict_insert(ctx->xml_ctx.ctx, "", 0);
3241 } else {
3242 last_subelem->arg = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
3243 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003244 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003245 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003246 }
3247 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003248
David Sedlákf250ecf2019-07-01 11:02:05 +02003249 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003250 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3251 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003252 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003253 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3254 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02003255 if (!name) {
3256 /* end of extension instance reached */
3257 break;
3258 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003259 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02003260 if (!e->child) {
3261 e->child = new_subelem;
3262 } else {
3263 last_subelem->next = new_subelem;
3264 }
3265 last_subelem = new_subelem;
3266 }
David Sedlák555c7202019-07-04 12:14:12 +02003267 } else {
3268 /* save text content */
David Sedlákbf8a2b72019-08-14 16:48:10 +02003269 LY_CHECK_RET(ret);
David Sedlák555c7202019-07-04 12:14:12 +02003270 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003271 e->argument = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlákbf8a2b72019-08-14 16:48:10 +02003272 LY_CHECK_ERR_RET(!e->argument, free(out), LY_EMEM);
David Sedlák555c7202019-07-04 12:14:12 +02003273 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003274 e->argument = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02003275 LY_CHECK_RET(!e->argument, LY_EMEM);
3276 }
David Sedlákda8ffa32019-07-08 14:17:10 +02003277 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlák555c7202019-07-04 12:14:12 +02003278 LY_CHECK_RET(name, LY_EINT);
David Sedlákb1a78352019-06-28 16:16:29 +02003279 }
David Sedlákb1a78352019-06-28 16:16:29 +02003280 }
3281
3282 return LY_SUCCESS;
3283}
3284
3285LY_ERR
David Sedlák4ffcec82019-07-25 15:10:21 +02003286yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char **data,
3287 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02003288{
3289 LY_ERR ret = LY_SUCCESS;
3290 const char *temp_prefix, *temp_name;
3291 char *out = NULL;
David Sedlák4ffcec82019-07-25 15:10:21 +02003292 size_t out_len, temp_name_len, temp_prefix_len, prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02003293 int dynamic;
3294 struct yin_arg_record *subelem_args = NULL;
3295 struct lysp_stmt *last = NULL, *new = NULL;
3296
3297 /* allocate new structure for element */
3298 *element = calloc(1, sizeof(**element));
David Sedlákda8ffa32019-07-08 14:17:10 +02003299 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, name, name_len);
3300 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003301
3302 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +02003303 /* load attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +02003304 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákb1a78352019-06-28 16:16:29 +02003305 /* add new element to linked-list */
3306 new = calloc(1, sizeof(*last));
David Sedlákda8ffa32019-07-08 14:17:10 +02003307 LY_CHECK_ERR_GOTO(ret, LOGMEM(ctx->xml_ctx.ctx), err);
David Sedlákb1a78352019-06-28 16:16:29 +02003308 if (!(*element)->child) {
3309 /* save first */
3310 (*element)->child = new;
3311 } else {
3312 last->next = new;
3313 }
3314 last = new;
3315
3316 last->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003317 ret = lyxml_get_attribute(&ctx->xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
David Sedlákb1a78352019-06-28 16:16:29 +02003318 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003319 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003320 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003321 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
3322 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003323 /* attributes with prefix are ignored */
3324 if (!temp_prefix) {
3325 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003326 last->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlákbf8a2b72019-08-14 16:48:10 +02003327 LY_CHECK_ERR_GOTO(!last->arg, free(out); LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003328 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003329 last->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
3330 LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003331 }
3332 }
3333 }
3334
3335 /* parse content of element */
David Sedlákda8ffa32019-07-08 14:17:10 +02003336 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003337 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003338 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákb1a78352019-06-28 16:16:29 +02003339 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003340 ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
David Sedlákb1a78352019-06-28 16:16:29 +02003341 LY_CHECK_GOTO(ret, err);
3342 if (!name) {
3343 /* end of element reached */
3344 break;
3345 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003346 ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, data, &last->next);
David Sedlákb1a78352019-06-28 16:16:29 +02003347 LY_CHECK_GOTO(ret, err);
3348 last = last->next;
3349 }
3350 } else {
3351 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +02003352 if (out_len != 0) {
3353 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003354 (*element)->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlákbf8a2b72019-08-14 16:48:10 +02003355 LY_CHECK_ERR_GOTO(!(*element)->arg, free(out); LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlák5392a212019-07-01 09:19:10 +02003356 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003357 (*element)->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
3358 LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003359 }
David Sedlákb1a78352019-06-28 16:16:29 +02003360 }
3361 /* read closing tag */
David Sedlákda8ffa32019-07-08 14:17:10 +02003362 ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
David Sedlákb1a78352019-06-28 16:16:29 +02003363 LY_CHECK_GOTO(ret, err);
3364 }
3365
David Sedlákb1a78352019-06-28 16:16:29 +02003366err:
David Sedlákda8ffa32019-07-08 14:17:10 +02003367 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003368 return ret;
3369}
3370
3371LY_ERR
David Sedlák4f03b932019-07-26 13:01:47 +02003372yin_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 +02003373{
David Sedlák81497a32019-08-13 16:56:26 +02003374 LY_ERR ret = LY_SUCCESS;
3375 struct yin_subelement *subelems = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003376
David Sedlák81497a32019-08-13 16:56:26 +02003377 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, YANG_MODULE));
3378 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
3379 YANG_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3380 YANG_ANYXML, &mod->data, 0,
3381 YANG_AUGMENT, &mod->augments, 0,
3382 YANG_CHOICE, &mod->data, 0,
3383 YANG_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3384 YANG_CONTAINER, &mod->data, 0,
3385 YANG_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3386 YANG_DEVIATION, &mod->deviations, 0,
3387 YANG_EXTENSION, &mod->extensions, 0,
3388 YANG_FEATURE, &mod->features, 0,
3389 YANG_GROUPING, &mod->groupings, 0,
3390 YANG_IDENTITY, &mod->identities, 0,
3391 YANG_IMPORT, mod->mod->prefix, &mod->imports, 0,
3392 YANG_INCLUDE, mod->mod->name, &mod->includes, 0,
3393 YANG_LEAF, &mod->data, 0,
3394 YANG_LEAF_LIST, &mod->data, 0,
3395 YANG_LIST, &mod->data, 0,
3396 YANG_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3397 YANG_NOTIFICATION, &mod->notifs, 0,
3398 YANG_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3399 YANG_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3400 YANG_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3401 YANG_REVISION, &mod->revs, 0,
3402 YANG_RPC, &mod->rpcs, 0,
3403 YANG_TYPEDEF, &mod->typedefs, 0,
3404 YANG_USES, &mod->data, 0,
3405 YANG_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3406 YANG_CUSTOM, NULL, 0
3407 ));
3408
3409 ret = yin_parse_content(ctx, subelems, 28, data, YANG_MODULE, NULL, &mod->exts);
3410 subelems_deallocator(28, subelems);
3411
3412 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003413}
3414
3415LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003416yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3417{
David Sedlák81497a32019-08-13 16:56:26 +02003418 LY_ERR ret = LY_SUCCESS;
3419 struct yin_subelement *subelems = NULL;
David Sedlák298ff6d2019-07-26 14:29:03 +02003420
David Sedlák81497a32019-08-13 16:56:26 +02003421 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, YANG_SUBMODULE));
3422 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
3423 YANG_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3424 YANG_ANYXML, &submod->data, 0,
3425 YANG_AUGMENT, &submod->augments, 0,
3426 YANG_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3427 YANG_CHOICE, &submod->data, 0,
3428 YANG_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3429 YANG_CONTAINER, &submod->data, 0,
3430 YANG_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3431 YANG_DEVIATION, &submod->deviations, 0,
3432 YANG_EXTENSION, &submod->extensions, 0,
3433 YANG_FEATURE, &submod->features, 0,
3434 YANG_GROUPING, &submod->groupings, 0,
3435 YANG_IDENTITY, &submod->identities, 0,
3436 YANG_IMPORT, submod->prefix, &submod->imports, 0,
3437 YANG_INCLUDE, submod->name, &submod->includes, 0,
3438 YANG_LEAF, &submod->data, 0,
3439 YANG_LEAF_LIST, &submod->data, 0,
3440 YANG_LIST, &submod->data, 0,
3441 YANG_NOTIFICATION, &submod->notifs, 0,
3442 YANG_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3443 YANG_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3444 YANG_REVISION, &submod->revs, 0,
3445 YANG_RPC, &submod->rpcs, 0,
3446 YANG_TYPEDEF, &submod->typedefs, 0,
3447 YANG_USES, &submod->data, 0,
3448 YANG_YANG_VERSION, &submod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3449 YANG_CUSTOM, NULL, 0
3450 ));
3451
3452 ret = yin_parse_content(ctx, subelems, 27, data, YANG_SUBMODULE, NULL, &submod->exts);
3453 subelems_deallocator(27, subelems);
3454
3455 return ret;
David Sedlák298ff6d2019-07-26 14:29:03 +02003456}
3457
3458LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02003459yin_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 +02003460{
3461 enum yang_keyword kw = YANG_NONE;
3462 LY_ERR ret = LY_SUCCESS;
3463 const char *prefix, *name;
3464 size_t prefix_len, name_len;
3465 struct yin_arg_record *attrs = NULL;
3466 struct lysp_submodule *mod_p = NULL;
3467
3468 /* create context */
3469 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003470 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003471 (*yin_ctx)->xml_ctx.ctx = ctx;
3472 (*yin_ctx)->xml_ctx.line = 1;
3473
David Sedlák1b623122019-08-05 15:27:49 +02003474 /* map the typedefs and groupings list from main context to the submodule's context */
3475 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3476 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3477
David Sedlák8985a142019-07-31 16:43:06 +02003478 /* check submodule */
3479 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3480 LY_CHECK_GOTO(ret, cleanup);
3481 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3482 LY_CHECK_GOTO(ret, cleanup);
3483 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
3484
3485 if (kw == YANG_MODULE) {
3486 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3487 ret = LY_EINVAL;
3488 goto cleanup;
3489 } else if (kw != YANG_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003490 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003491 ret = LY_EVALID;
3492 goto cleanup;
3493 }
3494
3495 mod_p = calloc(1, sizeof *mod_p);
3496 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3497 mod_p->parsing = 1;
3498
3499 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3500 LY_CHECK_GOTO(ret, cleanup);
3501
David Sedlák6d781b62019-08-02 15:22:52 +02003502 name = NULL;
David Sedlákbf8a2b72019-08-14 16:48:10 +02003503 /* skip possible trailing whitespaces at end of the input */
3504 while(*data && isspace(*data)) {
3505 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003506 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003507 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003508 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 +02003509 ret = LY_EVALID;
3510 goto cleanup;
3511 }
3512
David Sedlák8985a142019-07-31 16:43:06 +02003513 mod_p->parsing = 0;
3514 *submod = mod_p;
3515
3516cleanup:
3517 if (ret) {
3518 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003519 yin_parser_ctx_free(*yin_ctx);
3520 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003521 }
3522
3523 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3524 return ret;
3525}
3526
3527LY_ERR
3528yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003529{
David Sedláke4889912018-11-02 09:52:40 +01003530 LY_ERR ret = LY_SUCCESS;
3531 enum yang_keyword kw = YANG_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003532 struct lysp_module *mod_p = NULL;
3533 const char *prefix, *name;
3534 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003535 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003536
David Sedlák8985a142019-07-31 16:43:06 +02003537 /* create context */
3538 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003539 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003540 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
3541 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003542
David Sedlák8985a142019-07-31 16:43:06 +02003543 /* check module */
3544 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003545 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003546 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003547 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003548 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
David Sedláke4889912018-11-02 09:52:40 +01003549 if (kw == YANG_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003550 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 +01003551 ret = LY_EINVAL;
3552 goto cleanup;
3553 } else if (kw != YANG_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003554 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003555 ret = LY_EVALID;
3556 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003557 }
3558
David Sedlák3017da42019-02-15 09:48:04 +01003559 /* allocate module */
3560 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003561 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003562 mod_p->mod = mod;
3563 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003564
David Sedlák00250342019-06-21 14:19:39 +02003565 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003566 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003567 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003568
David Sedlákbf8a2b72019-08-14 16:48:10 +02003569 name = NULL;
3570 /* skip possible trailing whitespaces at end of the input */
3571 while(*data && isspace(*data)) {
3572 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003573 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003574 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003575 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 +02003576 ret = LY_EVALID;
3577 goto cleanup;
3578 }
3579
David Sedlák3017da42019-02-15 09:48:04 +01003580 mod_p->parsing = 0;
3581 mod->parsed = mod_p;
3582
3583cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003584 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003585 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003586 yin_parser_ctx_free(*yin_ctx);
3587 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003588 }
David Sedlák8985a142019-07-31 16:43:06 +02003589 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003590 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003591}