blob: 16662eea4b73ad9d7fbc3af4cbd9c738a2e54e13 [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ák169cc522019-08-15 13:23:45 +0200362 INSERT_STRING(ctx->xml_ctx.ctx, *arg_val, iter->dynamic_content, iter->content, iter->content_len);
363 iter->dynamic_content = 0;
364 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200365 } else {
David Sedlák1538a842019-08-08 15:38:51 +0200366 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 +0200367 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200368 }
369 }
370 }
371
David Sedlák292763b2019-07-09 11:10:53 +0200372 /* anything else than Y_MAYBE_STR_ARG is mandatory */
373 if (val_type != Y_MAYBE_STR_ARG && !found) {
David Sedlák9c40a922019-07-08 17:04:43 +0200374 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 +0200375 return LY_EVALID;
376 }
377
378 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200379}
380
David Sedlákd6e56892019-07-01 15:40:24 +0200381/**
David Sedlákda8ffa32019-07-08 14:17:10 +0200382 * @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 +0200383 *
384 * @param[in] type Type of wanted record.
385 * @param[in] array_size Size of array.
386 * @param[in] array Searched array.
387 *
388 * @return Pointer to desired record on success, NULL if element is not in the array.
389 */
David Sedlákb4e44562019-07-04 15:42:12 +0200390static struct yin_subelement *
David Sedlákb0faad82019-07-04 14:28:59 +0200391get_record(enum yang_keyword type, signed char array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200392{
David Sedlákb0faad82019-07-04 14:28:59 +0200393 signed char left = 0, right = array_size - 1, middle;
394
395 while (left <= right) {
396 middle = left + (right - left) / 2;
397
398 if (array[middle].type == type) {
399 return &array[middle];
400 }
401
402 if (array[middle].type < type) {
403 left = middle + 1;
404 } else {
405 right = middle - 1;
David Sedlákd6e56892019-07-01 15:40:24 +0200406 }
407 }
408
409 return NULL;
410}
411
David Sedlákbba38e52019-07-09 15:20:01 +0200412/**
413 * @brief Helper function to check mandatory constraint of subelement.
414 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200415 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200416 * @param[in] subelem_info Array of information about subelements.
417 * @param[in] subelem_info_size Size of subelem_info array.
418 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
419 *
420 * @return LY_ERR values.
421 */
422static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200423yin_check_subelem_mandatory_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedlákb0faad82019-07-04 14:28:59 +0200424 signed char subelem_info_size, enum yang_keyword current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200425{
David Sedlákb0faad82019-07-04 14:28:59 +0200426 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200427 /* 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 +0200428 if (subelem_info[i].flags & YIN_SUBELEM_MANDATORY && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200429 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200430 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200431 return LY_EVALID;
432 }
433 }
434
435 return LY_SUCCESS;
436}
437
David Sedlákbba38e52019-07-09 15:20:01 +0200438/**
439 * @brief Helper function to check "first" constraint of subelement.
440 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200441 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200442 * @param[in] subelem_info Array of information about subelements.
443 * @param[in] subelem_info_size Size of subelem_info array.
444 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200445 * @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 +0200446 *
447 * @return LY_ERR values.
448 */
449static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200450yin_check_subelem_first_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedláke1a30302019-07-10 13:49:38 +0200451 signed char subelem_info_size, enum yang_keyword current_element,
452 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200453{
David Sedlákb0faad82019-07-04 14:28:59 +0200454 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200455 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200456 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
457 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200458 return LY_EVALID;
459 }
460 }
461
462 return LY_SUCCESS;
463}
464
David Sedlákbba38e52019-07-09 15:20:01 +0200465/**
466 * @brief Helper function to check if array of information about subelements is in ascending order.
467 *
468 * @param[in] subelem_info Array of information about subelements.
469 * @param[in] subelem_info_size Size of subelem_info array.
470 *
471 * @return True iff subelem_info array is in ascending order, False otherwise.
472 */
David Sedlák5545f5d2019-07-11 11:55:16 +0200473#ifndef NDEBUG
David Sedlákbba38e52019-07-09 15:20:01 +0200474static bool
David Sedlákb0faad82019-07-04 14:28:59 +0200475is_ordered(struct yin_subelement *subelem_info, signed char subelem_info_size)
476{
David Sedlák292763b2019-07-09 11:10:53 +0200477 enum yang_keyword current = YANG_NONE; /* 0 (minimal value) */
David Sedlákb0faad82019-07-04 14:28:59 +0200478
479 for (signed char i = 0; i < subelem_info_size; ++i) {
480 if (subelem_info[i].type <= current) {
481 return false;
482 }
483 current = subelem_info[i].type;
484 }
485
486 return true;
487}
David Sedlák5545f5d2019-07-11 11:55:16 +0200488#endif
David Sedlákb0faad82019-07-04 14:28:59 +0200489
David Sedlákd6e56892019-07-01 15:40:24 +0200490/**
David Sedlákb4e44562019-07-04 15:42:12 +0200491 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
492 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200493 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200494 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200495 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákd6e56892019-07-01 15:40:24 +0200496 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákb4e44562019-07-04 15:42:12 +0200497 * @param[in] kw Type of current element.
498 * @param[out] value Where value of attribute should be stored.
499 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200500 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200501 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200502 *
David Sedlákd6e56892019-07-01 15:40:24 +0200503 * @return LY_ERR values.
504 */
David Sedlákb4e44562019-07-04 15:42:12 +0200505static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200506yin_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 +0200507 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 +0200508{
David Sedlák1f90d252019-07-10 17:09:32 +0200509 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200510 struct yin_subelement subelems[1] = {
511 {YANG_CUSTOM, NULL, 0}
512 };
David Sedlákb4e44562019-07-04 15:42:12 +0200513
David Sedlákda8ffa32019-07-08 14:17:10 +0200514 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200515}
516
517/**
David Sedlák6542aed2019-08-14 10:47:43 +0200518 * @brief Parse path element.
519 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200520 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200521 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
522 * @param[in,out] data Data to read from, always moved to currently handled character.
523 * @param[in] kw Type of current element.
524 * @param[out] type Type structure to store parsed value, flags and extension instances.
525 *
526 * @return LY_ERR values.
527 */
528static LY_ERR
529yin_parse_path(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
530 struct lysp_type *type)
531{
532 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
533 YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
534 type->flags |= LYS_SET_PATH;
535
536 return LY_SUCCESS;
537}
538
539/**
David Sedlákd3983112019-07-12 11:20:56 +0200540 * @brief Parse pattern element.
541 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200542 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd3983112019-07-12 11:20:56 +0200543 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
544 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200545 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200546 *
547 * @return LY_ERR values.
548 */
549static LY_ERR
550yin_parse_pattern(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
551 struct lysp_type *type)
552{
553 const char *real_value = NULL;
554 char *saved_value = NULL;
555 struct lysp_restr *restr;
556
557 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->patterns, restr, LY_EMEM);
558 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &real_value, Y_STR_ARG, YANG_PATTERN));
559 size_t len = strlen(real_value);
560
561 saved_value = malloc(len + 2);
562 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
563 memmove(saved_value + 1, real_value, len);
564 FREE_STRING(ctx->xml_ctx.ctx, real_value);
565 saved_value[0] = 0x06;
566 saved_value[len + 1] = '\0';
567 restr->arg = lydict_insert_zc(ctx->xml_ctx.ctx, saved_value);
568 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
569 type->flags |= LYS_SET_PATTERN;
570
571 struct yin_subelement subelems[6] = {
572 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
573 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
574 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
575 {YANG_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
576 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
577 {YANG_CUSTOM, NULL, 0}
578 };
579 return yin_parse_content(ctx, subelems, 6, data, YANG_PATTERN, NULL, &restr->exts);
580}
581
David Sedlákc5b20842019-08-13 10:18:31 +0200582/**
583 * @brief Parse fraction-digits element.
584 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200585 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200586 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
587 * @param[in,out] data Data to read from, always moved to currently handled character.
588 * @param[in,out] type Type structure to store value, flags and extension instances.
589 *
590 * @return LY_ERR values.
591 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200592static LY_ERR
593yin_parse_fracdigits(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
594 struct lysp_type *type)
595{
596 const char *temp_val = NULL;
597 char *ptr;
598 unsigned long int num;
599
600 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_FRACTION_DIGITS));
601
602 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200603 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200604 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
605 return LY_EVALID;
606 }
607
608 errno = 0;
609 num = strtoul(temp_val, &ptr, 10);
610 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200611 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200612 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
613 return LY_EVALID;
614 }
615 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200616 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200617 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
618 return LY_EVALID;
619 }
David Sedlák2ab5d8e2019-07-16 11:19:41 +0200620 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200621 type->fraction_digits = num;
622 type->flags |= LYS_SET_FRDIGITS;
623 struct yin_subelement subelems[1] = {
David Sedlákd1144562019-08-06 12:36:14 +0200624 {YANG_CUSTOM, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200625 };
626 return yin_parse_content(ctx, subelems, 1, data, YANG_FRACTION_DIGITS, NULL, &type->exts);
627}
628
David Sedlák07869a52019-07-12 14:28:19 +0200629/**
David Sedlák43801c92019-08-05 15:58:54 +0200630 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200631 *
632 * @param[in,out] ctx YIN parser context for logging and to store current state.
633 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
634 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200635 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200636 *
637 * @return LY_ERR values.
638 */
David Sedlákca36c422019-07-12 12:47:55 +0200639static LY_ERR
David Sedlák43801c92019-08-05 15:58:54 +0200640yin_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 +0200641{
David Sedlák07869a52019-07-12 14:28:19 +0200642 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200643
David Sedlák43801c92019-08-05 15:58:54 +0200644 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->enums, en, LY_EMEM);
645 type->flags |= LYS_SET_ENUM;
646 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_ENUM));
647 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
648 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
649 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200650
651 struct yin_subelement subelems[6] = {
David Sedlák07869a52019-07-12 14:28:19 +0200652 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
653 {YANG_IF_FEATURE, &en->iffeatures, 0},
David Sedlák07869a52019-07-12 14:28:19 +0200654 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
655 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
David Sedlák43801c92019-08-05 15:58:54 +0200656 {YANG_VALUE, en, YIN_SUBELEM_UNIQUE},
David Sedlákca36c422019-07-12 12:47:55 +0200657 {YANG_CUSTOM, NULL, 0}
658 };
David Sedlák43801c92019-08-05 15:58:54 +0200659 return yin_parse_content(ctx, subelems, 6, data, YANG_ENUM, NULL, &en->exts);
660}
661
662/**
663 * @brief Parse bit element.
664 *
665 * @param[in,out] ctx YIN parser context for logging and to store current state.
666 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
667 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200668 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200669 *
670 * @return LY_ERR values.
671 */
672static LY_ERR
673yin_parse_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
674 struct lysp_type *type)
675{
676 struct lysp_type_enum *en;
677
678 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->bits, en, LY_EMEM);
679 type->flags |= LYS_SET_BIT;
680 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_BIT));
681 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
682
683 struct yin_subelement subelems[6] = {
684 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
685 {YANG_IF_FEATURE, &en->iffeatures, 0},
686 {YANG_POSITION, en, YIN_SUBELEM_UNIQUE},
687 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
688 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
689 {YANG_CUSTOM, NULL, 0}
690 };
691 return yin_parse_content(ctx, subelems, 6, data, YANG_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200692}
693
David Sedlákd3983112019-07-12 11:20:56 +0200694/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200695 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
696 * more instances, such as base or if-feature.
697 *
698 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200699 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200700 * @param[in,out] data Data to read from, always moved to currently handled character.
701 * @param[in] kw Type of current element.
702 * @param[out] values Parsed values to add to.
703 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200704 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200705 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200706 *
707 * @return LY_ERR values.
708 */
709static LY_ERR
710yin_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 +0200711 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 +0200712{
713 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200714 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200715 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200716 struct yin_subelement subelems[1] = {
717 {YANG_CUSTOM, &index, 0}
718 };
719
David Sedlák1f90d252019-07-10 17:09:32 +0200720 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200721
722 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
723}
724
725/**
David Sedlák6542aed2019-08-14 10:47:43 +0200726 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
727 *
728 * @param[in,out] ctx YIN parser context for logging and to store current state.
729 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
730 * @param[in,out] data Data to read from, always moved to currently handled character.
731 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200732 * @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 +0200733 * @param[in] arg_type Expected type of attribute.
734 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200735 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200736 *
737 * @return LY_ERR values.
738 */
739static LY_ERR
740yin_parse_simple_elem(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
741 struct yin_subelement *subinfo, enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
742{
743 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
744 LY_CHECK_RET(yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subinfo->dest,
745 arg_type, arg_val_type, exts));
746 } else {
747 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subinfo->dest,
748 arg_type, arg_val_type, exts));
749 }
750
751 return LY_SUCCESS;
752}
753
754/**
755 * @brief Parse base element.
756 *
757 * @param[in,out] ctx YIN parser context for logging and to store current state.
758 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
759 * @param[in,out] data Data to read from, always moved to currently handled character.
760 * @param[in] parent Identification of parent element.
761 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200762 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200763 *
764 * @return LY_ERR values.
765 */
766static LY_ERR
767yin_parse_base(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword parent,
768 void *dest, struct lysp_ext_instance **exts)
769{
770 struct lysp_type *type = NULL;
771
772 if (parent == YANG_TYPE) {
773 type = (struct lysp_type *)dest;
774 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, YANG_BASE, &type->bases, YIN_ARG_NAME,
775 Y_PREF_IDENTIF_ARG, exts));
776 type->flags |= LYS_SET_BASE;
777 } else if (parent == YANG_IDENTITY) {
778 LY_CHECK_RET(yin_parse_simple_elements(ctx, attrs, data, YANG_BASE, (const char ***)dest,
779 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
780 } else {
781 LOGINT(ctx->xml_ctx.ctx);
782 return LY_EINT;
783 }
784
785 return LY_SUCCESS;
786}
787
788/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200789 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200790 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200791 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákcf5569a2019-07-11 13:31:34 +0200792 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
793 * @param[in,out] data Data to read from, always moved to currently handled character.
794 * @prama[out] type Type structure to store value, flag and extensions.
795 *
796 * @return LY_ERR values.
797 */
798static LY_ERR
799yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
800 const char **data, struct lysp_type *type)
801{
802 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200803 struct yin_subelement subelems[1] = {
804 {YANG_CUSTOM, NULL, 0}
805 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200806
807 type->flags |= LYS_SET_REQINST;
808 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_REQUIRE_INSTANCE));
809 if (strcmp(temp_val, "true") == 0) {
810 type->require_instance = 1;
811 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200812 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
813 "require-instance", "true", "false");
David Sedlákcf5569a2019-07-11 13:31:34 +0200814 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
815 return LY_EVALID;
816 }
817 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
818
819 return yin_parse_content(ctx, subelems, 1, data, YANG_REQUIRE_INSTANCE, NULL, &type->exts);
820}
821
822/**
David Sedlákce77bf52019-07-11 16:59:31 +0200823 * @brief Parse modifier element.
824 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200825 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200826 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
827 * @param[in,out] data Data to read from, always moved to currently handled character.
828 * @param[in,out] pat Value to write to.
829 * @param[in,out] exts Extension instances to add to.
830 *
831 * @return LY_ERR values.
832 */
833static LY_ERR
834yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
835 const char **pat, struct lysp_ext_instance **exts)
836{
David Sedlákd3983112019-07-12 11:20:56 +0200837 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200838 const char *temp_val;
839 char *modified_val;
840 struct yin_subelement subelems[1] = {
841 {YANG_CUSTOM, NULL, 0}
842 };
843
844 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MODIFIER));
845 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200846 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
847 "modifier", "invert-match");
David Sedlákce77bf52019-07-11 16:59:31 +0200848 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
849 return LY_EVALID;
850 }
David Sedlákd3983112019-07-12 11:20:56 +0200851 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200852
853 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200854 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200855 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200856 strcpy(modified_val, *pat);
857 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200858
859 /* modify the new value */
860 modified_val[0] = 0x15;
861 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
862
863 return yin_parse_content(ctx, subelems, 1, data, YANG_MODIFIER, NULL, exts);
864}
865
866/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200867 * @brief Parse a restriction element (length, range or one instance of must).
868 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200869 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb7296dd2019-07-11 14:58:38 +0200870 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
871 * @param[in,out] data Data to read from, always moved to currently handled character.
872 * @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 +0200873 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200874 */
875static LY_ERR
876yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
877 enum yang_keyword restr_kw, struct lysp_restr *restr)
878{
879 assert(restr_kw == YANG_MUST || restr_kw == YANG_LENGTH || restr_kw == YANG_RANGE);
880 struct yin_subelement subelems[5] = {
David Sedlák968ac342019-07-11 15:17:59 +0200881 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
882 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
883 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
884 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
885 {YANG_CUSTOM, NULL, 0}
886 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200887 /* argument of must is called condition, but argument of length and range is called value */
David Sedlákc5b20842019-08-13 10:18:31 +0200888 enum yin_argument arg_type = (restr_kw == YANG_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200889 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
890
891 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
892}
893
894/**
David Sedlák6542aed2019-08-14 10:47:43 +0200895 * @brief Parse range element.
896 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200897 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200898 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
899 * @param[in,out] data Data to read from, always moved to currently handled character.
900 * @param[out] type Type structure to store parsed value and flags.
901 *
902 * @return LY_ERR values.
903 */
904static LY_ERR
905yin_parse_range(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
906 const char **data, struct lysp_type *type)
907{
908 type->range = calloc(1, sizeof *type->range);
909 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
910 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, YANG_RANGE, type->range));
911 type->flags |= LYS_SET_RANGE;
912
913 return LY_SUCCESS;
914}
915
916/**
917 * @brief Parse length element.
918 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200919 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200920 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
921 * @param[in,out] data Data to read from, always moved to currently handled character.
922 * @param[out] type Type structure to store parsed value and flags.
923 *
924 * @return LY_ERR values.
925 */
926static LY_ERR
927yin_parse_length(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
928 const char **data, struct lysp_type *type)
929{
930 type->length = calloc(1, sizeof *type->length);
931 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
932 LY_CHECK_RET(yin_parse_restriction(ctx, attrs, data, YANG_LENGTH, type->length));
933 type->flags |= LYS_SET_LENGTH;
934
935 return LY_SUCCESS;
936}
937
938/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200939 * @brief Parse must element.
940 *
941 * @param[in,out] ctx YIN parser context for logging and to store current state.
942 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
943 * @param[in,out] data Data to read from, always moved to currently handled character.
944 * @param[in,out] restrs Restrictions to add to.
945 *
946 * @return LY_ERR values.
947 */
948static LY_ERR
949yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
950{
951 struct lysp_restr *restr;
952
953 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
954 return yin_parse_restriction(ctx, attrs, data, YANG_MUST, restr);
955}
956
957/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200958 * @brief Parse position or value element.
959 *
960 * @param[in,out] ctx YIN parser context for logging and to store current state.
961 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
962 * @param[in,out] data Data to read from, always moved to currently handled character.
963 * @param[in] kw Type of current element, can be set to YANG_POSITION or YANG_VALUE.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200964 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200965 *
966 * @return LY_ERR values.
967 */
968static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +0200969yin_parse_value_pos(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák5545f5d2019-07-11 11:55:16 +0200970 enum yang_keyword kw, struct lysp_type_enum *enm)
971{
972 assert(kw == YANG_POSITION || kw == YANG_VALUE);
973 const char *temp_val = NULL;
974 char *ptr;
975 long int num;
976 unsigned long int unum;
977
978 /* set value flag */
979 enm->flags |= LYS_SET_VALUE;
980
981 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200982 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 +0200983 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
984 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == YANG_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200985 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 +0200986 goto error;
987 }
988
989 /* convert value */
990 errno = 0;
991 if (kw == YANG_VALUE) {
992 num = strtol(temp_val, &ptr, 10);
993 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200994 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 +0200995 goto error;
996 }
997 } else {
998 unum = strtoul(temp_val, &ptr, 10);
999 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +02001000 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 +02001001 goto error;
1002 }
1003 }
1004 /* check if whole argument value was converted */
1005 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001006 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 +02001007 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +02001008 }
1009 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +02001010 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 +02001011 goto error;
1012 }
1013 /* save correctly ternary operator can't be used because num and unum have different signes */
1014 if (kw == YANG_VALUE) {
1015 enm->value = num;
1016 } else {
1017 enm->value = unum;
1018 }
1019 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1020
1021 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +02001022 struct yin_subelement subelems[1] = {
1023 {YANG_CUSTOM, NULL, 0}
1024 };
David Sedlák5545f5d2019-07-11 11:55:16 +02001025 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
1026
David Sedlákbf8a2b72019-08-14 16:48:10 +02001027error:
David Sedlák5545f5d2019-07-11 11:55:16 +02001028 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1029 return LY_EVALID;
1030}
1031
David Sedlák05404f62019-07-24 14:11:53 +02001032
1033/**
1034 * @brief Parse belongs-to element.
1035 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001036 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001037 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1038 * @param[in,out] data Data to read from, always moved to currently handled character.
1039 * @param[out] submod Structure of submodule that is being parsed.
1040 * @param[in,out] exts Extension instances to add to.
1041 *
1042 * @return LY_ERR values
1043 */
1044static LY_ERR
1045yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1046 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
1047{
1048 struct yin_subelement subelems[2] = {
1049 {YANG_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1050 {YANG_CUSTOM, NULL, 0}
1051 };
1052 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, YANG_BELONGS_TO));
1053
1054 return yin_parse_content(ctx, subelems, 2, data, YANG_BELONGS_TO, NULL, exts);
1055}
1056
David Sedlák5545f5d2019-07-11 11:55:16 +02001057/**
David Sedlákc1771b12019-07-10 15:55:46 +02001058 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001059 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001060 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001061 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001062 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákcf5569a2019-07-11 13:31:34 +02001063 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001064 * @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 +02001065 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001066 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001067 *
1068 * @return LY_ERR values.
1069 */
1070static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001071yin_parse_meta(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdf2a9732019-08-07 13:23:16 +02001072 enum yang_keyword elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +02001073{
1074 assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
1075
David Sedlák968ac342019-07-11 15:17:59 +02001076 struct yin_subelement subelems[2] = {
1077 {YANG_CUSTOM, NULL, 0},
1078 {YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1079 };
David Sedlákdf2a9732019-08-07 13:23:16 +02001080 /* check attributes */
1081 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 +02001082
David Sedlákdf2a9732019-08-07 13:23:16 +02001083 /* parse content */
David Sedlákda8ffa32019-07-08 14:17:10 +02001084 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001085}
1086
1087/**
David Sedlákc1771b12019-07-10 15:55:46 +02001088 * @brief Parse error-message element.
1089 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001090 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +02001091 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákc1771b12019-07-10 15:55:46 +02001092 * @param[in,out] data Data to read from.
1093 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001094 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001095 *
1096 * @return LY_ERR values.
1097 */
1098static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001099yin_parse_err_msg(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdf2a9732019-08-07 13:23:16 +02001100 const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +02001101{
David Sedlák968ac342019-07-11 15:17:59 +02001102 struct yin_subelement subelems[2] = {
1103 {YANG_CUSTOM, NULL, 0},
1104 {YIN_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1105 };
David Sedlákc1771b12019-07-10 15:55:46 +02001106
David Sedlákdf2a9732019-08-07 13:23:16 +02001107 /* check attributes */
1108 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, YANG_ERROR_MESSAGE));
1109
David Sedlákc1771b12019-07-10 15:55:46 +02001110 return yin_parse_content(ctx, subelems, 2, data, YANG_ERROR_MESSAGE, NULL, exts);
1111}
1112
1113/**
David Sedlák6542aed2019-08-14 10:47:43 +02001114 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001115 *
1116 * @param[in,out] ctx YIN parser context for logging and to store current state.
1117 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1118 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák6542aed2019-08-14 10:47:43 +02001119 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001120 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001121 *
1122 * @return LY_ERR values.
1123 */
1124static LY_ERR
David Sedlák6542aed2019-08-14 10:47:43 +02001125yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1126 enum yang_keyword parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001127{
David Sedlák6542aed2019-08-14 10:47:43 +02001128 struct lysp_type *type = NULL;
1129 if (parent == YANG_DEVIATE) {
1130 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
1131 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1132 type = *((struct lysp_type **)subinfo->dest);
1133 } else {
1134 type = (struct lysp_type *)subinfo->dest;
1135 }
1136 /* type as child of another type */
1137 if (parent == YANG_TYPE) {
1138 struct lysp_type *nested_type = NULL;
1139 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->types, nested_type, LY_EMEM);
1140 type->flags |= LYS_SET_TYPE;
1141 type = nested_type;
1142 }
David Sedlák374d2b32019-07-17 15:06:55 +02001143 struct yin_subelement subelems[11] = {
1144 {YANG_BASE, type, 0},
1145 {YANG_BIT, type, 0},
1146 {YANG_ENUM, type, 0},
1147 {YANG_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1148 {YANG_LENGTH, type, YIN_SUBELEM_UNIQUE},
1149 {YANG_PATH, type, YIN_SUBELEM_UNIQUE},
1150 {YANG_PATTERN, type, 0},
1151 {YANG_RANGE, type, YIN_SUBELEM_UNIQUE},
1152 {YANG_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1153 {YANG_TYPE, type},
1154 {YANG_CUSTOM, NULL, 0},
1155 };
1156 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, YANG_TYPE));
1157 return yin_parse_content(ctx, subelems, 11, data, YANG_TYPE, NULL, &type->exts);
1158}
1159
David Sedlák1af868e2019-07-17 17:03:14 +02001160/**
1161 * @brief Parse max-elements element.
1162 *
1163 * @param[in,out] ctx YIN parser context for logging and to store current state.
1164 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1165 * @param[in,out] data Data to read from, always moved to currently handled character.
1166 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001167 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001168 * @param[in,out] exts Extension instances to add to.
1169 *
1170 * @return LY_ERR values.
1171 */
1172static LY_ERR
1173yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
1174 uint16_t *flags, struct lysp_ext_instance **exts)
1175{
1176 const char *temp_val = NULL;
1177 char *ptr;
1178 unsigned long int num;
1179 struct yin_subelement subelems[1] = {
1180 {YANG_CUSTOM, NULL, 0},
1181 };
David Sedlák374d2b32019-07-17 15:06:55 +02001182
David Sedlák1af868e2019-07-17 17:03:14 +02001183 *flags |= LYS_SET_MAX;
1184 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MAX_ELEMENTS));
1185 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 +02001186 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001187 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1188 return LY_EVALID;
1189 }
1190
1191 if (strcmp(temp_val, "unbounded")) {
1192 errno = 0;
1193 num = strtoul(temp_val, &ptr, 10);
1194 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001195 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001196 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1197 return LY_EVALID;
1198 }
1199 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001200 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +02001201 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1202 return LY_EVALID;
1203 }
1204 *max = num;
1205 }
1206 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1207 return yin_parse_content(ctx, subelems, 1, data, YANG_MAX_ELEMENTS, NULL, exts);
1208}
David Sedlák374d2b32019-07-17 15:06:55 +02001209
1210/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001211 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001212 *
1213 * @param[in,out] ctx YIN parser context for logging and to store current state.
1214 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1215 * @param[in,out] data Data to read from, always moved to currently handled character.
1216 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001217 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001218 * @param[in,out] exts Extension instances to add to.
1219 *
1220 * @return LY_ERR values.
1221 */
1222static LY_ERR
1223yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
1224 uint16_t *flags, struct lysp_ext_instance **exts)
1225{
1226 const char *temp_val = NULL;
1227 char *ptr;
1228 unsigned long int num;
1229 struct yin_subelement subelems[1] = {
1230 {YANG_CUSTOM, NULL, 0},
1231 };
1232
1233 *flags |= LYS_SET_MIN;
David Sedláka2dad212019-07-18 12:45:19 +02001234 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 +02001235
1236 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001237 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001238 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1239 return LY_EVALID;
1240 }
1241
1242 errno = 0;
1243 num = strtoul(temp_val, &ptr, 10);
1244 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001245 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001246 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1247 return LY_EVALID;
1248 }
1249 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001250 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001251 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1252 return LY_EVALID;
1253 }
1254 *min = num;
1255 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001256 return yin_parse_content(ctx, subelems, 1, data, YANG_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001257}
1258
David Sedláka2dad212019-07-18 12:45:19 +02001259/**
1260 * @brief Parse min-elements or max-elements element.
1261 *
1262 * @param[in,out] ctx YIN parser context for logging and to store current state.
1263 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1264 * @param[in,out] data Data to read from, always moved to currently handled character.
1265 * @param[in] parent Identification of parent element.
1266 * @param[in] current Identification of current element.
1267 * @param[in] dest Where the parsed value and flags should be stored.
1268 *
1269 * @return LY_ERR values.
1270 */
David Sedlák09e18c92019-07-18 11:17:11 +02001271static LY_ERR
1272yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1273 enum yang_keyword parent, enum yang_keyword current, void *dest)
1274{
1275 assert(current == YANG_MAX_ELEMENTS || current == YANG_MIN_ELEMENTS);
David Sedlák4ffcec82019-07-25 15:10:21 +02001276 assert(parent == YANG_LEAF_LIST || parent == YANG_REFINE || parent == YANG_LIST || parent == YANG_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001277 uint32_t *lim;
1278 uint16_t *flags;
1279 struct lysp_ext_instance **exts;
1280
1281 if (parent == YANG_LEAF_LIST) {
1282 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
1283 flags = &((struct lysp_node_leaflist *)dest)->flags;
1284 exts = &((struct lysp_node_leaflist *)dest)->exts;
1285 } else if (parent == YANG_REFINE) {
1286 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
1287 flags = &((struct lysp_refine *)dest)->flags;
1288 exts = &((struct lysp_refine *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001289 } else if (parent == YANG_LIST) {
David Sedlák09e18c92019-07-18 11:17:11 +02001290 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
1291 flags = &((struct lysp_node_list *)dest)->flags;
1292 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001293 } else {
1294 lim = ((struct minmax_dev_meta *)dest)->lim;
1295 flags = ((struct minmax_dev_meta *)dest)->flags;
1296 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001297 }
1298
1299 if (current == YANG_MAX_ELEMENTS) {
1300 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1301 } else {
1302 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1303 }
1304
1305 return LY_SUCCESS;
1306}
1307
1308/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001309 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001310 *
1311 * @param[in,out] ctx YIN parser context for logging and to store current state.
1312 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1313 * @param[in,out] data Data to read from, always moved to currently handled character.
1314 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001315 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001316 *
1317 * @return LY_ERR values.
1318 */
1319static LY_ERR
1320yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1321 uint16_t *flags, struct lysp_ext_instance **exts)
1322{
1323 const char *temp_val;
1324 struct yin_subelement subelems[1] = {
1325 {YANG_CUSTOM, NULL, 0},
1326 };
1327
1328 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_ORDERED_BY));
1329 if (strcmp(temp_val, "system") == 0) {
1330 *flags |= LYS_ORDBY_SYSTEM;
1331 } else if (strcmp(temp_val, "user") == 0) {
1332 *flags |= LYS_ORDBY_USER;
1333 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001334 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1335 "ordered-by", "system", "user");
David Sedláka2dad212019-07-18 12:45:19 +02001336 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1337 return LY_EVALID;
1338 }
1339 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1340
1341 return yin_parse_content(ctx, subelems, 1, data, YANG_ORDERED_BY, NULL, exts);
1342}
1343
1344/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001345 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001346 *
1347 * @param[in,out] ctx YIN parser context for logging and to store current state.
1348 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1349 * @param[in,out] data Data to read from, always moved to currently handled character.
1350 * @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 +02001351 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001352 *
1353 * @return LY_ERR values.
1354 */
1355static LY_ERR
1356yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1357 enum yang_keyword any_kw, struct tree_node_meta *node_meta)
1358{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001359 struct lysp_node_anydata *any;
1360
David Sedlák8d552d62019-08-06 15:29:05 +02001361 /* create new sibling */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001362 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, any, next);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001363 any->nodetype = (any_kw == YANG_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
1364 any->parent = node_meta->parent;
1365
David Sedlákbf8a2b72019-08-14 16:48:10 +02001366 /* parse argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001367 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 +02001368
1369 struct yin_subelement subelems[9] = {
1370 {YANG_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1371 {YANG_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1372 {YANG_IF_FEATURE, &any->iffeatures, 0},
1373 {YANG_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1374 {YANG_MUST, &any->musts, 0},
1375 {YANG_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1376 {YANG_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1377 {YANG_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1378 {YANG_CUSTOM, NULL, 0},
1379 };
1380 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1381}
1382
1383/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001384 * @brief parse leaf element.
1385 *
1386 * @param[in,out] ctx YIN parser context for logging and to store current state.
1387 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1388 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001389 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001390 *
1391 * @return LY_ERR values.
1392 */
1393static LY_ERR
1394yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1395 struct tree_node_meta *node_meta)
1396{
David Sedlák203ca3a2019-07-18 15:26:25 +02001397 struct lysp_node_leaf *leaf;
1398
David Sedlák8d552d62019-08-06 15:29:05 +02001399 /* create structure new leaf */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001400 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, leaf, next);
David Sedlák203ca3a2019-07-18 15:26:25 +02001401 leaf->nodetype = LYS_LEAF;
1402 leaf->parent = node_meta->parent;
1403
David Sedlák203ca3a2019-07-18 15:26:25 +02001404 /* parser argument */
1405 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, YANG_LEAF));
1406
1407 /* parse content */
1408 struct yin_subelement subelems[12] = {
1409 {YANG_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1410 {YANG_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1411 {YANG_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1412 {YANG_IF_FEATURE, &leaf->iffeatures, 0},
1413 {YANG_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1414 {YANG_MUST, &leaf->musts, 0},
1415 {YANG_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1416 {YANG_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1417 {YANG_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1418 {YANG_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1419 {YANG_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1420 {YANG_CUSTOM, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001421 };
David Sedlák203ca3a2019-07-18 15:26:25 +02001422 return yin_parse_content(ctx, subelems, 12, data, YANG_LEAF, NULL, &leaf->exts);
1423}
1424
1425/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001426 * @brief Parse leaf-list element.
1427 *
1428 * @param[in,out] ctx YIN parser context for logging and to store current state.
1429 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1430 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001431 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001432 *
1433 * @return LY_ERR values.
1434 */
1435static LY_ERR
1436yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1437 struct tree_node_meta *node_meta)
1438{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001439 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001440
David Sedlákbf8a2b72019-08-14 16:48:10 +02001441 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, llist, next);
David Sedlák8d552d62019-08-06 15:29:05 +02001442
David Sedlákc3da3ef2019-07-19 12:56:08 +02001443 llist->nodetype = LYS_LEAFLIST;
1444 llist->parent = node_meta->parent;
1445
David Sedlákc3da3ef2019-07-19 12:56:08 +02001446 /* parse argument */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001447 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 +02001448
1449 /* parse content */
1450 struct yin_subelement subelems[14] = {
1451 {YANG_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1452 {YANG_DEFAULT, &llist->dflts, 0},
1453 {YANG_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1454 {YANG_IF_FEATURE, &llist->iffeatures, 0},
1455 {YANG_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1456 {YANG_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1457 {YANG_MUST, &llist->musts, 0},
1458 {YANG_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1459 {YANG_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1460 {YANG_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1461 {YANG_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1462 {YANG_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1463 {YANG_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1464 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001465 };
David Sedlákc3da3ef2019-07-19 12:56:08 +02001466 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, YANG_LEAF_LIST, NULL, &llist->exts));
1467
David Sedlákbf8a2b72019-08-14 16:48:10 +02001468 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001469 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001470 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001471 return LY_EVALID;
1472 }
1473 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001474 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001475 return LY_EVALID;
1476 }
1477
1478 return LY_SUCCESS;
1479}
1480
1481/**
David Sedlák04e17b22019-07-19 15:29:48 +02001482 * @brief Parse typedef element.
1483 *
1484 * @param[in,out] ctx YIN parser context for logging and to store current state.
1485 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1486 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001487 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001488 *
1489 * @return LY_ERR values.
1490 */
1491static LY_ERR
1492yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02001493 struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001494{
1495 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001496 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
David Sedlák6881b512019-08-13 12:52:00 +02001497 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001498
1499 /* parse argument */
1500 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, YANG_TYPEDEF));
1501
1502 /* parse content */
1503 struct yin_subelement subelems[7] = {
1504 {YANG_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1505 {YANG_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1506 {YANG_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1507 {YANG_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1508 {YANG_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1509 {YANG_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1510 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001511 };
David Sedlák04e17b22019-07-19 15:29:48 +02001512 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, YANG_TYPEDEF, NULL, &tpdf->exts));
1513
1514 /* store data for collision check */
1515 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
David Sedláke8b74df2019-08-14 14:18:22 +02001516 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0) == -1, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001517 }
1518
1519 return LY_SUCCESS;
1520}
1521
1522/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001523 * @brief Parse refine element.
1524 *
1525 * @param[in,out] ctx YIN parser context for logging and to store current state.
1526 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1527 * @param[in,out] data Data to read from, always moved to currently handled character.
1528 * @param[in,out] refines Refines to add to.
1529 *
1530 * @return LY_ERR values.
1531 */
1532static LY_ERR
1533yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1534 struct lysp_refine **refines)
1535{
1536 struct lysp_refine *rf;
1537
1538 /* allocate new refine */
1539 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1540
1541 /* parse attribute */
1542 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, YANG_REFINE));
1543 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1544
1545 /* parse content */
1546 struct yin_subelement subelems[11] = {
1547 {YANG_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1548 {YANG_DEFAULT, &rf->dflts, 0},
1549 {YANG_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1550 {YANG_IF_FEATURE, &rf->iffeatures, 0},
1551 {YANG_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1552 {YANG_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1553 {YANG_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1554 {YANG_MUST, &rf->musts, 0},
1555 {YANG_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1556 {YANG_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1557 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001558 };
David Sedlákd2d676a2019-07-22 11:28:19 +02001559 return yin_parse_content(ctx, subelems, 11, data, YANG_REFINE, NULL, &rf->exts);
1560}
1561
1562/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001563 * @brief Parse uses element.
1564 *
1565 * @param[in,out] ctx YIN parser context for logging and to store current state.
1566 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1567 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001568 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001569 *
1570 * @return LY_ERR values.
1571 */
1572static LY_ERR
1573yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1574 struct tree_node_meta *node_meta)
1575{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001576 struct lysp_node_uses *uses;
1577
David Sedlák8d552d62019-08-06 15:29:05 +02001578 /* create new uses */
David Sedlákbf8a2b72019-08-14 16:48:10 +02001579 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, uses, next);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001580 uses->nodetype = LYS_USES;
1581 uses->parent = node_meta->parent;
1582
David Sedlák0d6de5a2019-07-22 13:25:44 +02001583 /* parse argument */
1584 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, YANG_USES));
1585
1586 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001587 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001588 struct yin_subelement subelems[8] = {
1589 {YANG_AUGMENT, &augments, 0},
1590 {YANG_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1591 {YANG_IF_FEATURE, &uses->iffeatures, 0},
1592 {YANG_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1593 {YANG_REFINE, &uses->refines, 0},
1594 {YANG_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1595 {YANG_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1596 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001597 };
David Sedlák0d6de5a2019-07-22 13:25:44 +02001598 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, YANG_USES, NULL, &uses->exts));
1599 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1600
1601 return LY_SUCCESS;
1602}
1603
1604/**
David Sedlákaa854b02019-07-22 14:17:10 +02001605 * @brief Parse revision element.
1606 *
1607 * @param[in,out] ctx YIN parser context for logging and to store current state.
1608 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1609 * @param[in,out] data Data to read from, always moved to currently handled character.
1610 * @param[in,out] revs Parsed revisions to add to.
1611 *
1612 * @return LY_ERR values.
1613 */
1614static LY_ERR
1615yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1616 struct lysp_revision **revs)
1617{
1618 struct lysp_revision *rev;
1619 const char *temp_date = NULL;
1620
1621 /* allocate new reivison */
1622 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1623
1624 /* parse argument */
1625 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, YANG_REVISION));
1626 /* check value */
1627 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1628 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1629 return LY_EVALID;
1630 }
1631 strcpy(rev->date, temp_date);
1632 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1633
1634 /* parse content */
1635 struct yin_subelement subelems[3] = {
1636 {YANG_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1637 {YANG_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1638 {YANG_CUSTOM, NULL, 0},
1639 };
1640 return yin_parse_content(ctx, subelems, 3, data, YANG_REVISION, NULL, &rev->exts);
1641}
1642
David Sedlák5e13dea2019-07-22 16:06:45 +02001643/**
1644 * @brief Parse include element.
1645 *
1646 * @param[in,out] ctx YIN parser context for logging and to store current state.
1647 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1648 * @param[in,out] data Data to read from, always moved to currently handled character.
1649 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1650 *
1651 * @return LY_ERR values.
1652 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001653static LY_ERR
1654yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1655 struct include_meta *inc_meta)
1656{
1657 struct lysp_include *inc;
1658
1659 /* allocate new include */
1660 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1661
1662 /* parse argument */
1663 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, YANG_INCLUDE));
1664
1665 /* submodules share the namespace with the module names, so there must not be
1666 * a module of the same name in the context, no need for revision matching */
1667 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 +02001668 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001669 return LY_EVALID;
1670 }
1671
1672 /* parse content */
1673 struct yin_subelement subelems[4] = {
1674 {YANG_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1675 {YANG_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1676 {YANG_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1677 {YANG_CUSTOM, NULL, 0},
1678 };
1679 return yin_parse_content(ctx, subelems, 4, data, YANG_INCLUDE, NULL, &inc->exts);
1680}
1681
David Sedlákaa854b02019-07-22 14:17:10 +02001682/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001683 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001684 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001685 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001686 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of revision-date element.
1687 * @param[in,out] data Data to read from, always moved to currently handled character.
1688 * @param[in,out] rev Array to store the parsed value in.
1689 * @param[in,out] exts Extension instances to add to.
1690 *
1691 * @return LY_ERR values.
1692 */
1693static LY_ERR
1694yin_parse_revision_date(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, char *rev,
1695 struct lysp_ext_instance **exts)
1696{
1697 const char *temp_rev;
1698 struct yin_subelement subelems[1] = {
1699 {YANG_CUSTOM, NULL, 0}
1700 };
1701
1702 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, YANG_REVISION_DATE));
1703 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
1704 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
1705
1706 strcpy(rev, temp_rev);
1707 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
1708
1709 return yin_parse_content(ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
1710}
1711
1712/**
1713 * @brief Parse config element.
1714 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001715 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001716 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1717 * @param[in,out] data Data to read from, always moved to currently handled character.
1718 * @param[in,out] flags Flags to add to.
1719 * @param[in,out] exts Extension instances to add to.
1720 *
1721 * @return LY_ERR values.
1722 */
1723static LY_ERR
1724yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1725 struct lysp_ext_instance **exts)
1726{
1727 const char *temp_val = NULL;
1728 struct yin_subelement subelems[1] = {
1729 {YANG_CUSTOM, NULL, 0}
1730 };
1731
1732 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_CONFIG));
1733 if (strcmp(temp_val, "true") == 0) {
1734 *flags |= LYS_CONFIG_W;
1735 } else if (strcmp(temp_val, "false") == 0) {
1736 *flags |= LYS_CONFIG_R;
1737 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001738 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
1739 "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001740 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1741 return LY_EVALID;
1742 }
1743 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1744
1745 return yin_parse_content(ctx, subelems, 1, data, YANG_CONFIG, NULL, exts);
1746}
1747
1748/**
1749 * @brief Parse yang-version element.
1750 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001751 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001752 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yang-version element.
1753 * @param[in] data Data to read from, always moved to currently handled character.
1754 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001755 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001756 *
1757 * @return LY_ERR values.
1758 */
1759static LY_ERR
1760yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
1761 struct lysp_ext_instance **exts)
1762{
1763 const char *temp_version = NULL;
1764 struct yin_subelement subelems[1] = {
1765 {YANG_CUSTOM, NULL, 0}
1766 };
1767
1768 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, YANG_YANG_VERSION));
1769 if (strcmp(temp_version, "1.0") == 0) {
1770 *version = LYS_VERSION_1_0;
1771 } else if (strcmp(temp_version, "1.1") == 0) {
1772 *version = LYS_VERSION_1_1;
1773 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001774 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
1775 "yang-version", "1.0", "1.1");
David Sedlákdfbbb442019-08-06 16:33:21 +02001776 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1777 return LY_EVALID;
1778 }
1779 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1780 ctx->mod_version = *version;
1781
1782 return yin_parse_content(ctx, subelems, 1, data, YANG_YANG_VERSION, NULL, exts);
1783}
1784
1785/**
1786 * @brief Parse import element.
1787 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001788 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001789 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1790 * @param[in,out] data Data to read from, always moved to currently handled character.
1791 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1792 *
1793 * @return LY_ERR values.
1794 */
1795static LY_ERR
1796yin_parse_import(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct import_meta *imp_meta)
1797{
1798 struct lysp_import *imp;
1799 /* allocate new element in sized array for import */
1800 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
1801
1802 struct yin_subelement subelems[5] = {
1803 {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1804 {YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1805 {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1806 {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1807 {YANG_CUSTOM, NULL, 0}
1808 };
1809
1810 /* parse import attributes */
1811 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, YANG_IMPORT));
1812 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
1813 /* check prefix validity */
1814 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1815
1816 return LY_SUCCESS;
1817}
1818
1819/**
1820 * @brief Parse mandatory element.
1821 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001822 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001823 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1824 * @param[in,out] data Data to read from, always moved to currently handled character.
1825 * @param[in,out] flags Flags to add to.
1826 * @param[in,out] exts Extension instances to add to.
1827 *
1828 * @return LY_ERR values.
1829 */
1830static LY_ERR
1831yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1832 struct lysp_ext_instance **exts)
1833{
1834 const char *temp_val = NULL;
1835 struct yin_subelement subelems[1] = {
1836 {YANG_CUSTOM, NULL, 0}
1837 };
1838
1839 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MANDATORY));
1840 if (strcmp(temp_val, "true") == 0) {
1841 *flags |= LYS_MAND_TRUE;
1842 } else if (strcmp(temp_val, "false") == 0) {
1843 *flags |= LYS_MAND_FALSE;
1844 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001845 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1846 "mandatory", "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001847 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1848 return LY_EVALID;
1849 }
1850 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1851
1852 return yin_parse_content(ctx, subelems, 1, data, YANG_MANDATORY, NULL, exts);
1853}
1854
1855/**
1856 * @brief Parse status element.
1857 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001858 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001859 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1860 * @param[in,out] data Data to read from, always moved to currently handled character.
1861 * @param[in,out] flags Flags to add to.
1862 * @param[in,out] exts Extension instances to add to.
1863 *
1864 * @return LY_ERR values.
1865 */
1866static LY_ERR
1867yin_parse_status(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1868 struct lysp_ext_instance **exts)
1869{
1870 const char *value = NULL;
1871 struct yin_subelement subelems[1] = {
1872 {YANG_CUSTOM, NULL, 0}
1873 };
1874
1875 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &value, Y_STR_ARG, YANG_STATUS));
1876 if (strcmp(value, "current") == 0) {
1877 *flags |= LYS_STATUS_CURR;
1878 } else if (strcmp(value, "deprecated") == 0) {
1879 *flags |= LYS_STATUS_DEPRC;
1880 } else if (strcmp(value, "obsolete") == 0) {
1881 *flags |= LYS_STATUS_OBSLT;
1882 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001883 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
1884 "status", "current", "deprecated", "obsolete");
David Sedlákdfbbb442019-08-06 16:33:21 +02001885 FREE_STRING(ctx->xml_ctx.ctx, value);
1886 return LY_EVALID;
1887 }
1888 FREE_STRING(ctx->xml_ctx.ctx, value);
1889
1890 return yin_parse_content(ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
1891}
1892
1893/**
1894 * @brief Parse when element.
1895 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001896 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001897 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of when element.
1898 * @param[in,out] data Data to read from, always moved to currently handled character.
1899 * @param[out] when_p When pointer to parse to.
1900 */
1901static LY_ERR
1902yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
1903{
1904 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001905 LY_ERR ret = LY_SUCCESS;
1906
David Sedlákdfbbb442019-08-06 16:33:21 +02001907 when = calloc(1, sizeof *when);
1908 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedláka56e0012019-08-15 13:21:25 +02001909 ret = yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, YANG_WHEN);
1910 LY_CHECK_ERR_RET(ret, free(when), ret);
1911
David Sedlákdfbbb442019-08-06 16:33:21 +02001912 *when_p = when;
1913 struct yin_subelement subelems[3] = {
1914 {YANG_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1915 {YANG_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1916 {YANG_CUSTOM, NULL, 0}
1917 };
1918
1919 return yin_parse_content(ctx, subelems, 3, data, YANG_WHEN, NULL, &when->exts);
1920}
1921
1922/**
1923 * @brief Parse yin-elemenet element.
1924 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001925 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001926 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yin-element element.
1927 * @param[in,out] data Data to read from, always moved to currently handled position.
1928 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001929 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001930 *
1931 * @return LY_ERR values.
1932 */
1933static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001934yin_parse_yin_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdfbbb442019-08-06 16:33:21 +02001935 uint16_t *flags, struct lysp_ext_instance **exts)
1936{
1937 const char *temp_val = NULL;
1938 struct yin_subelement subelems[1] = {
1939 {YANG_CUSTOM, NULL, 0}
1940 };
1941
1942 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_YIN_ELEMENT));
1943 if (strcmp(temp_val, "true") == 0) {
1944 *flags |= LYS_YINELEM_TRUE;
1945 } else if (strcmp(temp_val, "false") == 0) {
1946 *flags |= LYS_YINELEM_FALSE;
1947 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001948 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1949 "yin-element", "true", "false");
David Sedlákdfbbb442019-08-06 16:33:21 +02001950 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1951 return LY_EVALID;
1952 }
1953 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1954
1955 return yin_parse_content(ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
1956}
1957
1958/**
1959 * @brief Parse argument element.
1960 *
1961 * @param[in,out] xml_ctx Xml context.
1962 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of argument element.
1963 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001964 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1965 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001966 *
1967 * @return LY_ERR values.
1968 */
1969static LY_ERR
David Sedlákdf2691f2019-08-15 13:32:27 +02001970yin_parse_argument(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlákdfbbb442019-08-06 16:33:21 +02001971 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
1972{
1973 struct yin_subelement subelems[2] = {
1974 {YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1975 {YANG_CUSTOM, NULL, 0}
1976 };
1977
1978 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, YANG_ARGUMENT));
1979
1980 return yin_parse_content(ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
1981}
1982
1983/**
1984 * @brief Parse the extension statement.
1985 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001986 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001987 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension element.
1988 * @param[in,out] data Data to read from.
1989 * @param[in,out] extensions Extensions to add to.
1990 *
1991 * @return LY_ERR values.
1992 */
1993static LY_ERR
1994yin_parse_extension(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_ext **extensions)
1995{
1996 struct lysp_ext *ex;
1997 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
1998 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ex->name, Y_IDENTIF_ARG, YANG_EXTENSION));
1999
2000 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
2001 struct yin_subelement subelems[5] = {
2002 {YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2003 {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2004 {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2005 {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2006 {YANG_CUSTOM, NULL, 0}
2007 };
2008
2009 return yin_parse_content(ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
2010}
2011
2012/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002013 * @brief Parse feature element.
2014 *
2015 * @param[in,out] ctx YIN parser context for logging and to store current state.
2016 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2017 * @param[in,out] data Data to read from, always moved to currently handled character.
2018 * @param[in,out] features Features to add to.
2019 *
2020 * @return LY_ERR values.
2021 */
2022static LY_ERR
2023yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2024 struct lysp_feature **features)
2025{
2026 struct lysp_feature *feat;
2027
2028 /* allocate new feature */
2029 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
2030
2031 /* parse argument */
2032 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, YANG_FEATURE));
2033
2034 /* parse content */
2035 struct yin_subelement subelems[5] = {
2036 {YANG_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2037 {YANG_IF_FEATURE, &feat->iffeatures, 0},
2038 {YANG_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2039 {YANG_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2040 {YANG_CUSTOM, NULL, 0},
2041 };
2042 return yin_parse_content(ctx, subelems, 5, data, YANG_FEATURE, NULL, &feat->exts);
2043}
2044
2045/**
David Sedlák28794f22019-07-22 16:45:00 +02002046 * @brief Parse identity element.
2047 *
2048 * @param[in,out] ctx YIN parser context for logging and to store current state.
2049 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2050 * @param[in,out] data Data to read from, always moved to currently handled character.
2051 * @param[in,out] identities Identities to add to.
2052 *
2053 * @return LY_ERR values.
2054 */
2055static LY_ERR
2056yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2057 struct lysp_ident **identities)
2058{
2059 struct lysp_ident *ident;
2060
2061 /* allocate new identity */
2062 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
2063
2064 /* parse argument */
2065 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, YANG_IDENTITY));
2066
2067 /* parse content */
2068 struct yin_subelement subelems[6] = {
2069 {YANG_BASE, &ident->bases, 0},
2070 {YANG_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2071 {YANG_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2072 {YANG_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2073 {YANG_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2074 {YANG_CUSTOM, NULL, 0},
2075 };
2076 return yin_parse_content(ctx, subelems, 6, data, YANG_IDENTITY, NULL, &ident->exts);
2077}
2078
2079/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002080 * @brief Parse list element.
2081 *
2082 * @param[in,out] ctx YIN parser context for logging and to store current state.
2083 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2084 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002085 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002086 *
2087 * @return LY_ERR values.
2088 */
2089static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02002090yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2091 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002092{
David Sedlákaf536aa2019-07-23 13:42:23 +02002093 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002094 LY_ERR ret = LY_SUCCESS;
2095 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02002096
David Sedlákbf8a2b72019-08-14 16:48:10 +02002097 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, list, next);
David Sedlákaf536aa2019-07-23 13:42:23 +02002098 list->nodetype = LYS_LIST;
2099 list->parent = node_meta->parent;
2100
David Sedlákaf536aa2019-07-23 13:42:23 +02002101 /* parse argument */
2102 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, YANG_LIST));
2103
2104 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02002105 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
2106 YANG_ACTION, &list->actions, 0,
2107 YANG_ANYDATA, &list->child, 0,
2108 YANG_ANYXML, &list->child, 0,
2109 YANG_CHOICE, &list->child, 0,
2110 YANG_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2111 YANG_CONTAINER, &list->child, 0,
2112 YANG_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2113 YANG_GROUPING, &list->groupings, 0,
2114 YANG_IF_FEATURE, &list->iffeatures, 0,
2115 YANG_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2116 YANG_LEAF, &list->child, 0,
2117 YANG_LEAF_LIST, &list->child, 0,
2118 YANG_LIST, &list->child, 0,
2119 YANG_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2120 YANG_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2121 YANG_MUST, &list->musts, 0,
2122 YANG_NOTIFICATION, &list->notifs, 0,
2123 YANG_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2124 YANG_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2125 YANG_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2126 YANG_TYPEDEF, &list->typedefs, 0,
2127 YANG_UNIQUE, &list->uniques, 0,
2128 YANG_USES, &list->child, 0,
2129 YANG_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2130 YANG_CUSTOM, NULL, 0
2131 ));
2132 ret = yin_parse_content(ctx, subelems, 25, data, YANG_LIST, NULL, &list->exts);
2133 subelems_deallocator(25, subelems);
2134 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002135
2136 /* finalize parent pointers to the reallocated items */
2137 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
2138
2139 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02002140 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002141 return LY_EVALID;
2142 }
2143
2144 return LY_SUCCESS;
2145}
2146
2147/**
David Sedlák031b9e72019-07-23 15:19:37 +02002148 * @brief Parse notification element.
2149 *
2150 * @param[in,out] ctx YIN parser context for logging and to store current state.
2151 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2152 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02002153 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002154 *
2155 * @return LY_ERR values.
2156 */
2157static LY_ERR
2158yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002159 struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002160{
2161 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002162 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002163 LY_ERR ret = LY_SUCCESS;
2164 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002165
2166 /* allocate new notification */
David Sedlák6881b512019-08-13 12:52:00 +02002167 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002168 notif->nodetype = LYS_NOTIF;
2169 notif->parent = notif_meta->parent;
2170
2171 /* parse argument */
2172 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, YANG_NOTIFICATION));
2173
2174 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002175 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
2176 YANG_ANYDATA, &notif->data, 0,
2177 YANG_ANYXML, &notif->data, 0,
2178 YANG_CHOICE, &notif->data, 0,
2179 YANG_CONTAINER, &notif->data, 0,
2180 YANG_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2181 YANG_GROUPING, &notif->groupings, 0,
2182 YANG_IF_FEATURE, &notif->iffeatures, 0,
2183 YANG_LEAF, &notif->data, 0,
2184 YANG_LEAF_LIST, &notif->data, 0,
2185 YANG_LIST, &notif->data, 0,
2186 YANG_MUST, &notif->musts, YIN_SUBELEM_VER2,
2187 YANG_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2188 YANG_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2189 YANG_TYPEDEF, &notif->typedefs, 0,
2190 YANG_USES, &notif->data, 0,
2191 YANG_CUSTOM, NULL, 0
2192 ));
2193
2194 ret = yin_parse_content(ctx, subelems, 16, data, YANG_NOTIFICATION, NULL, &notif->exts);
2195 subelems_deallocator(16, subelems);
2196 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002197
2198 /* finalize parent pointers to the reallocated items */
2199 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2200
2201 return LY_SUCCESS;
2202}
2203
2204/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002205 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002206 *
2207 * @param[in,out] ctx YIN parser context for logging and to store current state.
2208 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2209 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002210 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002211 *
2212 * @return LY_ERR values.
2213 */
2214static LY_ERR
2215yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002216 struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002217{
2218 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002219 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002220 LY_ERR ret = LY_SUCCESS;
2221 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002222
2223 /* create new grouping */
David Sedlák6881b512019-08-13 12:52:00 +02002224 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002225 grp->nodetype = LYS_GROUPING;
2226 grp->parent = gr_meta->parent;
2227
2228 /* parse argument */
2229 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, YANG_GROUPING));
2230
2231 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002232 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
2233 YANG_ACTION, &grp->actions, 0,
2234 YANG_ANYDATA, &grp->data, 0,
2235 YANG_ANYXML, &grp->data, 0,
2236 YANG_CHOICE, &grp->data, 0,
2237 YANG_CONTAINER, &grp->data, 0,
2238 YANG_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2239 YANG_GROUPING, &grp->groupings, 0,
2240 YANG_LEAF, &grp->data, 0,
2241 YANG_LEAF_LIST, &grp->data, 0,
2242 YANG_LIST, &grp->data, 0,
2243 YANG_NOTIFICATION, &grp->notifs, 0,
2244 YANG_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2245 YANG_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2246 YANG_TYPEDEF, &grp->typedefs, 0,
2247 YANG_USES, &grp->data, 0,
2248 YANG_CUSTOM, NULL, 0
2249 ));
2250 ret = yin_parse_content(ctx, subelems, 16, data, YANG_GROUPING, NULL, &grp->exts);
2251 subelems_deallocator(16, subelems);
2252 LY_CHECK_RET(ret);
2253
David Sedláke3ce9ef2019-07-23 16:34:30 +02002254 /* finalize parent pointers to the reallocated items */
2255 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2256
2257 return LY_SUCCESS;
2258}
2259
2260/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002261 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002262 *
2263 * @param[in,out] ctx YIN parser context for logging and to store current state.
2264 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2265 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002266 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002267 *
2268 * @return LY_ERR values.
2269 */
2270static LY_ERR
2271yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2272 struct tree_node_meta *node_meta)
2273{
David Sedlákf111bcb2019-07-23 17:15:51 +02002274 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002275 LY_ERR ret = LY_SUCCESS;
2276 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002277
2278 /* create new container */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002279 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, cont, next);
David Sedlákf111bcb2019-07-23 17:15:51 +02002280 cont->nodetype = LYS_CONTAINER;
2281 cont->parent = node_meta->parent;
2282
David Sedlákf111bcb2019-07-23 17:15:51 +02002283 /* parse aegument */
2284 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, YANG_CONTAINER));
2285
2286 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002287 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
2288 YANG_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2289 YANG_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2290 YANG_ANYXML, &cont->child, 0,
2291 YANG_CHOICE, &cont->child, 0,
2292 YANG_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2293 YANG_CONTAINER, &cont->child, 0,
2294 YANG_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2295 YANG_GROUPING, &cont->groupings, 0,
2296 YANG_IF_FEATURE, &cont->iffeatures, 0,
2297 YANG_LEAF, &cont->child, 0,
2298 YANG_LEAF_LIST, &cont->child, 0,
2299 YANG_LIST, &cont->child, 0,
2300 YANG_MUST, &cont->musts, 0,
2301 YANG_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2302 YANG_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2303 YANG_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2304 YANG_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2305 YANG_TYPEDEF, &cont->typedefs, 0,
2306 YANG_USES, &cont->child, 0,
2307 YANG_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2308 YANG_CUSTOM, NULL, 0
2309 ));
2310 ret = yin_parse_content(ctx, subelems, 21, data, YANG_CONTAINER, NULL, &cont->exts);
2311 subelems_deallocator(21, subelems);
2312 LY_CHECK_RET(ret);
2313
David Sedlákf111bcb2019-07-23 17:15:51 +02002314 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2315
2316 return LY_SUCCESS;
2317}
2318
2319/**
David Sedlák5379d392019-07-24 10:42:03 +02002320 * @brief Parse case element.
2321 *
2322 * @param[in,out] ctx YIN parser context for logging and to store current state.
2323 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2324 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002325 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002326 *
2327 * @return LY_ERR values.
2328 */
2329static LY_ERR
2330yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2331 struct tree_node_meta *node_meta)
2332{
David Sedlák5379d392019-07-24 10:42:03 +02002333 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002334 LY_ERR ret = LY_SUCCESS;
2335 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002336
2337 /* create new case */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002338 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, cas, next);
David Sedlák5379d392019-07-24 10:42:03 +02002339 cas->nodetype = LYS_CASE;
2340 cas->parent = node_meta->parent;
2341
David Sedlák5379d392019-07-24 10:42:03 +02002342 /* parse argument */
2343 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, YANG_CASE));
2344
2345 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002346 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
2347 YANG_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2348 YANG_ANYXML, &cas->child, 0,
2349 YANG_CHOICE, &cas->child, 0,
2350 YANG_CONTAINER, &cas->child, 0,
2351 YANG_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2352 YANG_IF_FEATURE, &cas->iffeatures, 0,
2353 YANG_LEAF, &cas->child, 0,
2354 YANG_LEAF_LIST, &cas->child, 0,
2355 YANG_LIST, &cas->child, 0,
2356 YANG_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2357 YANG_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2358 YANG_USES, &cas->child, 0,
2359 YANG_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2360 YANG_CUSTOM, NULL, 0
2361 ));
2362 ret = yin_parse_content(ctx, subelems, 14, data, YANG_CASE, NULL, &cas->exts);
2363 subelems_deallocator(14, subelems);
2364
2365 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002366}
2367
2368/**
David Sedlák05404f62019-07-24 14:11:53 +02002369 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002370 *
2371 * @param[in,out] ctx YIN parser context for logging and to store current state.
2372 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2373 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002374 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002375 *
2376 * @return LY_ERR values.
2377 */
2378LY_ERR
2379yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2380 struct tree_node_meta *node_meta)
2381{
David Sedlák81497a32019-08-13 16:56:26 +02002382 LY_ERR ret = LY_SUCCESS;
2383 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002384 struct lysp_node_choice *choice;
2385
2386 /* create new choice */
David Sedlákbf8a2b72019-08-14 16:48:10 +02002387 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->nodes, choice, next);
David Sedlák8d552d62019-08-06 15:29:05 +02002388
David Sedlákb7abcfa2019-07-24 12:33:35 +02002389 choice->nodetype = LYS_CHOICE;
2390 choice->parent = node_meta->parent;
2391
David Sedlákb7abcfa2019-07-24 12:33:35 +02002392 /* parse argument */
2393 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, YANG_CHOICE));
2394
2395 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002396 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
2397 YANG_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2398 YANG_ANYXML, &choice->child, 0,
2399 YANG_CASE, &choice->child, 0,
2400 YANG_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2401 YANG_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2402 YANG_CONTAINER, &choice->child, 0,
2403 YANG_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2404 YANG_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2405 YANG_IF_FEATURE, &choice->iffeatures, 0,
2406 YANG_LEAF, &choice->child, 0,
2407 YANG_LEAF_LIST, &choice->child, 0,
2408 YANG_LIST, &choice->child, 0,
2409 YANG_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2410 YANG_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2411 YANG_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2412 YANG_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2413 YANG_CUSTOM, NULL, 0
2414 ));
2415 ret = yin_parse_content(ctx, subelems, 17, data, YANG_CHOICE, NULL, &choice->exts);
2416 subelems_deallocator(17, subelems);
2417 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002418}
2419
2420/**
David Sedlák05404f62019-07-24 14:11:53 +02002421 * @brief Parse input or output element.
2422 *
2423 * @param[in,out] ctx YIN parser context for logging and to store current state.
2424 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2425 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002426 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002427 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2428 *
2429 * @return LY_ERR values.
2430 */
2431static LY_ERR
2432yin_parse_inout(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword inout_kw,
2433 struct inout_meta *inout_meta)
2434{
David Sedlák81497a32019-08-13 16:56:26 +02002435 LY_ERR ret = LY_SUCCESS;
2436 struct yin_subelement *subelems = NULL;
2437
David Sedlák05404f62019-07-24 14:11:53 +02002438 /* initiate structure */
2439 inout_meta->inout_p->nodetype = (inout_kw == YANG_INPUT) ? LYS_INPUT : LYS_OUTPUT;
2440 inout_meta->inout_p->parent = inout_meta->parent;
2441
2442 /* check attributes */
2443 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
2444
2445 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002446 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
2447 YANG_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2448 YANG_ANYXML, &inout_meta->inout_p->data, 0,
2449 YANG_CHOICE, &inout_meta->inout_p->data, 0,
2450 YANG_CONTAINER, &inout_meta->inout_p->data, 0,
2451 YANG_GROUPING, &inout_meta->inout_p->groupings, 0,
2452 YANG_LEAF, &inout_meta->inout_p->data, 0,
2453 YANG_LEAF_LIST, &inout_meta->inout_p->data, 0,
2454 YANG_LIST, &inout_meta->inout_p->data, 0,
2455 YANG_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2456 YANG_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2457 YANG_USES, &inout_meta->inout_p->data, 0,
2458 YANG_CUSTOM, NULL, 0
2459 ));
2460 ret = yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts);
2461 subelems_deallocator(12, subelems);
2462 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002463
2464 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002465 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 +02002466
2467 return LY_SUCCESS;
2468}
2469
David Sedlák992fb7c2019-07-24 16:51:01 +02002470/**
2471 * @brief Parse action element.
2472 *
2473 * @param[in,out] ctx YIN parser context for logging and to store current state.
2474 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2475 * @param[in,out] data Data to read from, always moved to currently handled character.
2476 * @param[in] act_meta Meta information about parent node and actions to add to.
2477 *
2478 * @return LY_ERR values.
2479 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002480static LY_ERR
2481yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002482 struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002483{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002484 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002485 LY_ERR ret = LY_SUCCESS;
2486 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002487
2488 /* create new action */
David Sedlák6881b512019-08-13 12:52:00 +02002489 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *acts, act, LY_EMEM);
David Sedlák85d0eca2019-07-24 15:15:21 +02002490 act->nodetype = LYS_ACTION;
2491 act->parent = act_meta->parent;
2492
2493 /* parse argument */
2494 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, YANG_ACTION));
2495
2496 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002497 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
2498 YANG_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2499 YANG_GROUPING, &act->groupings, 0,
2500 YANG_IF_FEATURE, &act->iffeatures, 0,
2501 YANG_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2502 YANG_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2503 YANG_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2504 YANG_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2505 YANG_TYPEDEF, &act->typedefs, 0,
2506 YANG_CUSTOM, NULL, 0
2507 ));
2508 ret = (yin_parse_content(ctx, subelems, 9, data, YANG_ACTION, NULL, &act->exts));
2509 subelems_deallocator(9, subelems);
2510 LY_CHECK_RET(ret);
2511
David Sedlák85d0eca2019-07-24 15:15:21 +02002512 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2513
2514 return LY_SUCCESS;
2515}
2516
David Sedlák05404f62019-07-24 14:11:53 +02002517/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002518 * @brief Parse augment element.
2519 *
2520 * @param[in,out] ctx YIN parser context for logging and to store current state.
2521 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2522 * @param[in,out] data Data to read from, always moved to currently handled character.
2523 * @param[in] aug_meta Meta information about parent node and augments to add to.
2524 *
2525 * @return LY_ERR values.
2526 */
2527static LY_ERR
2528yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002529 struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002530{
2531 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002532 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002533 LY_ERR ret = LY_SUCCESS;
2534 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002535
2536 /* create new augment */
David Sedlák6881b512019-08-13 12:52:00 +02002537 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002538 aug->nodetype = LYS_AUGMENT;
2539 aug->parent = aug_meta->parent;
2540
2541 /* parse argument */
2542 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, YANG_AUGMENT));
2543 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2544
2545 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002546 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
2547 YANG_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2548 YANG_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2549 YANG_ANYXML, &aug->child, 0,
2550 YANG_CASE, &aug->child, 0,
2551 YANG_CHOICE, &aug->child, 0,
2552 YANG_CONTAINER, &aug->child, 0,
2553 YANG_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2554 YANG_IF_FEATURE, &aug->iffeatures, 0,
2555 YANG_LEAF, &aug->child, 0,
2556 YANG_LEAF_LIST, &aug->child, 0,
2557 YANG_LIST, &aug->child, 0,
2558 YANG_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2559 YANG_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2560 YANG_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2561 YANG_USES, &aug->child, 0,
2562 YANG_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2563 YANG_CUSTOM, NULL, 0
2564 ));
2565 ret = yin_parse_content(ctx, subelems, 17, data, YANG_AUGMENT, NULL, &aug->exts);
2566 subelems_deallocator(17, subelems);
2567 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002568
2569 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2570
2571 return LY_SUCCESS;
2572}
2573
David Sedlák8b754462019-07-25 16:22:13 +02002574/**
2575 * @brief Parse deviate element.
2576 *
2577 * @param[in,out] ctx YIN parser context for logging and to store current state.
2578 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2579 * @param[in,out] data Data to read from, always moved to currently handled character.
2580 * @param[in] deviates Deviates to add to.
2581 *
2582 * @return LY_ERR values.
2583 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002584static LY_ERR
2585yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2586 struct lysp_deviate **deviates)
2587{
2588 LY_ERR ret = LY_SUCCESS;
2589 uint8_t dev_mod;
2590 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002591 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002592 struct lysp_deviate_add *d_add = NULL;
2593 struct lysp_deviate_rpl *d_rpl = NULL;
2594 struct lysp_deviate_del *d_del = NULL;
2595
2596 /* parse argument */
2597 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_DEVIATE));
2598
2599 if (strcmp(temp_val, "not-supported") == 0) {
2600 dev_mod = LYS_DEV_NOT_SUPPORTED;
2601 } else if (strcmp(temp_val, "add") == 0) {
2602 dev_mod = LYS_DEV_ADD;
2603 } else if (strcmp(temp_val, "replace") == 0) {
2604 dev_mod = LYS_DEV_REPLACE;
2605 } else if (strcmp(temp_val, "delete") == 0) {
2606 dev_mod = LYS_DEV_DELETE;
2607 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002608 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
2609 "not-supported", "add", "replace", "delete");
David Sedlák4ffcec82019-07-25 15:10:21 +02002610 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2611 return LY_EVALID;
2612 }
2613 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2614
2615 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2616 d = calloc(1, sizeof *d);
2617 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2618 struct yin_subelement subelems[1] = {
2619 {YANG_CUSTOM, NULL, 0}
2620 };
2621 ret = yin_parse_content(ctx, subelems, 1, data, YANG_DEVIATE, NULL, &d->exts);
2622
2623 } else if (dev_mod == LYS_DEV_ADD) {
2624 d_add = calloc(1, sizeof *d_add);
2625 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2626 d = (struct lysp_deviate *)d_add;
2627 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2628 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2629 struct yin_subelement subelems[9] = {
2630 {YANG_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2631 {YANG_DEFAULT, &d_add->dflts, 0},
2632 {YANG_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2633 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2634 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2635 {YANG_MUST, &d_add->musts, 0},
2636 {YANG_UNIQUE, &d_add->uniques, 0},
2637 {YANG_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2638 {YANG_CUSTOM, NULL, 0},
2639 };
2640 ret = yin_parse_content(ctx, subelems, 9, data, YANG_DEVIATE, NULL, &d_add->exts);
2641
2642 } else if (dev_mod == LYS_DEV_REPLACE) {
2643 d_rpl = calloc(1, sizeof *d_rpl);
2644 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2645 d = (struct lysp_deviate *)d_rpl;
2646 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2647 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2648 struct yin_subelement subelems[8] = {
2649 {YANG_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2650 {YANG_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2651 {YANG_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2652 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2653 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2654 {YANG_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2655 {YANG_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2656 {YANG_CUSTOM, NULL, 0},
2657 };
2658 ret = yin_parse_content(ctx, subelems, 8, data, YANG_DEVIATE, NULL, &d_rpl->exts);
2659
2660 } else {
2661 d_del = calloc(1, sizeof *d_del);
2662 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2663 d = (struct lysp_deviate *)d_del;
2664 struct yin_subelement subelems[5] = {
2665 {YANG_DEFAULT, &d_del->dflts, 0},
2666 {YANG_MUST, &d_del->musts, 0},
2667 {YANG_UNIQUE, &d_del->uniques, 0},
2668 {YANG_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2669 {YANG_CUSTOM, NULL, 0},
2670 };
2671 ret = yin_parse_content(ctx, subelems, 5, data, YANG_DEVIATE, NULL, &d_del->exts);
2672 }
2673 LY_CHECK_GOTO(ret, cleanup);
2674
2675 d->mod = dev_mod;
2676 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002677 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002678
2679 return ret;
2680
2681cleanup:
2682 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002683 return ret;
2684}
2685
David Sedlák992fb7c2019-07-24 16:51:01 +02002686/**
David Sedlák8b754462019-07-25 16:22:13 +02002687 * @brief Parse deviation element.
2688 *
2689 * @param[in,out] ctx YIN parser context for logging and to store current state.
2690 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2691 * @param[in,out] data Data to read from, always moved to currently handled character.
2692 * @param[in] deviations Deviations to add to.
2693 *
2694 * @return LY_ERR values.
2695 */
2696static LY_ERR
2697yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2698 struct lysp_deviation **deviations)
2699{
2700 struct lysp_deviation *dev;
2701
2702 /* create new deviation */
2703 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2704
2705 /* parse argument */
David Sedlák1538a842019-08-08 15:38:51 +02002706 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 +02002707 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2708 struct yin_subelement subelems[4] = {
2709 {YANG_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2710 {YANG_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2711 {YANG_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2712 {YANG_CUSTOM, NULL, 0},
2713 };
David Sedlák1538a842019-08-08 15:38:51 +02002714 return yin_parse_content(ctx, subelems, 4, data, YANG_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002715}
2716
2717/**
David Sedlákb4e44562019-07-04 15:42:12 +02002718 * @brief Map keyword type to substatement info.
2719 *
2720 * @param[in] kw Keyword type.
2721 *
2722 * @return correct LYEXT_SUBSTMT information.
2723 */
2724static LYEXT_SUBSTMT
2725kw2lyext_substmt(enum yang_keyword kw)
2726{
2727 switch (kw) {
2728 case YANG_ARGUMENT:
2729 return LYEXT_SUBSTMT_ARGUMENT;
2730 case YANG_BASE:
2731 return LYEXT_SUBSTMT_BASE;
2732 case YANG_BELONGS_TO:
2733 return LYEXT_SUBSTMT_BELONGSTO;
2734 case YANG_CONTACT:
2735 return LYEXT_SUBSTMT_CONTACT;
2736 case YANG_DEFAULT:
2737 return LYEXT_SUBSTMT_DEFAULT;
2738 case YANG_DESCRIPTION:
2739 return LYEXT_SUBSTMT_DESCRIPTION;
2740 case YANG_ERROR_APP_TAG:
2741 return LYEXT_SUBSTMT_ERRTAG;
2742 case YANG_ERROR_MESSAGE:
2743 return LYEXT_SUBSTMT_ERRMSG;
2744 case YANG_KEY:
2745 return LYEXT_SUBSTMT_KEY;
2746 case YANG_NAMESPACE:
2747 return LYEXT_SUBSTMT_NAMESPACE;
2748 case YANG_ORGANIZATION:
2749 return LYEXT_SUBSTMT_ORGANIZATION;
2750 case YANG_PATH:
2751 return LYEXT_SUBSTMT_PATH;
2752 case YANG_PREFIX:
2753 return LYEXT_SUBSTMT_PREFIX;
2754 case YANG_PRESENCE:
2755 return LYEXT_SUBSTMT_PRESENCE;
2756 case YANG_REFERENCE:
2757 return LYEXT_SUBSTMT_REFERENCE;
2758 case YANG_REVISION_DATE:
2759 return LYEXT_SUBSTMT_REVISIONDATE;
2760 case YANG_UNITS:
2761 return LYEXT_SUBSTMT_UNITS;
2762 case YANG_VALUE:
2763 return LYEXT_SUBSTMT_VALUE;
2764 case YANG_YANG_VERSION:
2765 return LYEXT_SUBSTMT_VERSION;
2766 case YANG_MODIFIER:
2767 return LYEXT_SUBSTMT_MODIFIER;
2768 case YANG_REQUIRE_INSTANCE:
2769 return LYEXT_SUBSTMT_REQINSTANCE;
2770 case YANG_YIN_ELEMENT:
2771 return LYEXT_SUBSTMT_YINELEM;
2772 case YANG_CONFIG:
2773 return LYEXT_SUBSTMT_CONFIG;
2774 case YANG_MANDATORY:
2775 return LYEXT_SUBSTMT_MANDATORY;
2776 case YANG_ORDERED_BY:
2777 return LYEXT_SUBSTMT_ORDEREDBY;
2778 case YANG_STATUS:
2779 return LYEXT_SUBSTMT_STATUS;
2780 case YANG_FRACTION_DIGITS:
2781 return LYEXT_SUBSTMT_FRACDIGITS;
2782 case YANG_MAX_ELEMENTS:
2783 return LYEXT_SUBSTMT_MAX;
2784 case YANG_MIN_ELEMENTS:
2785 return LYEXT_SUBSTMT_MIN;
2786 case YANG_POSITION:
2787 return LYEXT_SUBSTMT_POSITION;
2788 case YANG_UNIQUE:
2789 return LYEXT_SUBSTMT_UNIQUE;
2790 case YANG_IF_FEATURE:
2791 return LYEXT_SUBSTMT_IFFEATURE;
2792 default:
2793 return LYEXT_SUBSTMT_SELF;
2794 }
2795}
2796
David Sedlákc5b20842019-08-13 10:18:31 +02002797/**
2798 * @brief map keyword to keyword-group.
2799 *
2800 * @param[in] ctx YIN parser context used for logging.
2801 * @param[in] kw Keyword that is child of module or submodule.
2802 * @param[out] group Group of keyword.
2803 *
2804 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2805 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002806static LY_ERR
2807kw2kw_group(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_module_stmt *group)
2808{
2809 switch (kw) {
2810 /* module header */
2811 case YANG_NONE:
2812 case YANG_NAMESPACE:
2813 case YANG_PREFIX:
2814 case YANG_BELONGS_TO:
2815 case YANG_YANG_VERSION:
2816 *group = Y_MOD_MODULE_HEADER;
2817 break;
2818 /* linkage */
2819 case YANG_INCLUDE:
2820 case YANG_IMPORT:
2821 *group = Y_MOD_LINKAGE;
2822 break;
2823 /* meta */
2824 case YANG_ORGANIZATION:
2825 case YANG_CONTACT:
2826 case YANG_DESCRIPTION:
2827 case YANG_REFERENCE:
2828 *group = Y_MOD_META;
2829 break;
2830 /* revision */
2831 case YANG_REVISION:
2832 *group = Y_MOD_REVISION;
2833 break;
2834 /* body */
2835 case YANG_ANYDATA:
2836 case YANG_ANYXML:
2837 case YANG_AUGMENT:
2838 case YANG_CHOICE:
2839 case YANG_CONTAINER:
2840 case YANG_DEVIATION:
2841 case YANG_EXTENSION:
2842 case YANG_FEATURE:
2843 case YANG_GROUPING:
2844 case YANG_IDENTITY:
2845 case YANG_LEAF:
2846 case YANG_LEAF_LIST:
2847 case YANG_LIST:
2848 case YANG_NOTIFICATION:
2849 case YANG_RPC:
2850 case YANG_TYPEDEF:
2851 case YANG_USES:
2852 case YANG_CUSTOM:
2853 *group = Y_MOD_BODY;
2854 break;
2855 default:
2856 LOGINT(ctx->xml_ctx.ctx);
2857 return LY_EINT;
2858 }
2859
2860 return LY_SUCCESS;
2861}
2862
David Sedlákc5b20842019-08-13 10:18:31 +02002863/**
2864 * @brief Check if relative order of two keywords is valid.
2865 *
2866 * @param[in] ctx YIN parser context used for logging.
2867 * @param[in] kw Current keyword.
2868 * @param[in] next_kw Next keyword.
2869 * @param[in] parrent Identification of parrent element, can be se to to YANG_MODULE of YANG_SUBMODULE,
2870 * because relative order is required only in module and submodule sub-elements, used for logging.
2871 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002872 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002873 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002874static LY_ERR
2875yin_check_relative_order(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_keyword next_kw, enum yang_keyword parrent)
2876{
2877 assert(parrent == YANG_MODULE || parrent == YANG_SUBMODULE);
2878 enum yang_module_stmt gr, next_gr;
2879
2880 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2881 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2882
2883 if (gr > next_gr) {
2884 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2885 return LY_EVALID;
2886 }
2887
2888 return LY_SUCCESS;
2889}
2890
David Sedlákd6e56892019-07-01 15:40:24 +02002891LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002892yin_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 +02002893 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 +02002894{
2895 LY_ERR ret = LY_SUCCESS;
David Sedlák8e7bda82019-07-16 17:57:50 +02002896 char *out = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +02002897 const char *prefix, *name;
2898 size_t out_len = 0, prefix_len, name_len;
David Sedlák8e7bda82019-07-16 17:57:50 +02002899 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002900 struct yin_arg_record *attrs = NULL;
David Sedláke6cd89e2019-08-07 12:46:02 +02002901 enum yang_keyword kw = YANG_NONE, last_kw = YANG_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002902 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002903
David Sedlákb0faad82019-07-04 14:28:59 +02002904 assert(is_ordered(subelem_info, subelem_info_size));
David Sedlákd6e56892019-07-01 15:40:24 +02002905
David Sedlákda8ffa32019-07-08 14:17:10 +02002906 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2907 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002908 /* current element has subelements as content */
2909 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002910 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákc5b20842019-08-13 10:18:31 +02002911 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákd6e56892019-07-01 15:40:24 +02002912 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +02002913 if (!name) {
David Sedlákd6e56892019-07-01 15:40:24 +02002914 /* end of current element reached */
2915 break;
2916 }
David Sedlák1af868e2019-07-17 17:03:14 +02002917 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002918 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6cd89e2019-08-07 12:46:02 +02002919 last_kw = kw;
David Sedlákc5b20842019-08-13 10:18:31 +02002920 kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002921
2922 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002923 subelem = get_record(kw, subelem_info_size, subelem_info);
2924 if (!subelem) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002925 if (current_element == YANG_DEVIATE && isdevsub(kw)) {
2926 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2927 } else {
David Sedlákc5b20842019-08-13 10:18:31 +02002928 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(current_element));
David Sedlák4ffcec82019-07-25 15:10:21 +02002929 }
David Sedlákd6e56892019-07-01 15:40:24 +02002930 ret = LY_EVALID;
2931 goto cleanup;
2932 }
2933
David Sedlák6542aed2019-08-14 10:47:43 +02002934 /* relative order is required only in module and submodule sub-elements */
David Sedláke6cd89e2019-08-07 12:46:02 +02002935 if (current_element == YANG_MODULE || current_element == YANG_SUBMODULE) {
2936 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2937 LY_CHECK_GOTO(ret, cleanup);
2938 }
David Sedlák5f8191e2019-07-08 16:35:52 +02002939
David Sedlák4ffcec82019-07-25 15:10:21 +02002940 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002941 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002942 /* subelement uniquenes */
David Sedlák1538a842019-08-08 15:38:51 +02002943 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +02002944 return LY_EVALID;
2945 }
David Sedlák1af868e2019-07-17 17:03:14 +02002946 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002947 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002948 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002949 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002950 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002951 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002952 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002953 if (ctx->mod_version < 2) {
David Sedlák1538a842019-08-08 15:38:51 +02002954 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák9bb1c042019-07-22 16:45:37 +02002955 ret = LY_EVALID;
2956 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002957 }
2958 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002959 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002960 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002961
David Sedlákd6e56892019-07-01 15:40:24 +02002962 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002963 /* call responsible function */
David Sedlákd6e56892019-07-01 15:40:24 +02002964 case YANG_CUSTOM:
David Sedlákc5b20842019-08-13 10:18:31 +02002965 ret = yin_parse_extension_instance(ctx, attrs, data, name2fullname(name, prefix_len),
2966 namelen2fulllen(name_len, prefix_len),
David Sedlák1af868e2019-07-17 17:03:14 +02002967 kw2lyext_substmt(current_element),
2968 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002969 break;
2970 case YANG_ACTION:
David Sedlákeaa45792019-07-24 15:25:01 +02002971 case YANG_RPC:
David Sedlák6881b512019-08-13 12:52:00 +02002972 ret = yin_parse_action(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002973 break;
2974 case YANG_ANYDATA:
David Sedlákd6e56892019-07-01 15:40:24 +02002975 case YANG_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002976 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002977 break;
2978 case YANG_ARGUMENT:
David Sedlákdf2691f2019-08-15 13:32:27 +02002979 ret = yin_parse_argument(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002980 break;
2981 case YANG_AUGMENT:
David Sedlák6881b512019-08-13 12:52:00 +02002982 ret = yin_parse_augment(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002983 break;
2984 case YANG_BASE:
David Sedlák6542aed2019-08-14 10:47:43 +02002985 ret = yin_parse_base(ctx, attrs, data, current_element, subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002986 break;
2987 case YANG_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002988 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002989 break;
2990 case YANG_BIT:
David Sedlák43801c92019-08-05 15:58:54 +02002991 ret = yin_parse_bit(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002992 break;
2993 case YANG_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002994 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002995 break;
2996 case YANG_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002997 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002998 break;
2999 case YANG_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02003000 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003001 break;
3002 case YANG_CONTACT:
David Sedlák619db942019-07-03 14:47:30 +02003003 case YANG_DESCRIPTION:
3004 case YANG_ORGANIZATION:
3005 case YANG_REFERENCE:
David Sedlákdf2691f2019-08-15 13:32:27 +02003006 ret = yin_parse_meta(ctx, attrs, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003007 break;
3008 case YANG_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02003009 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003010 break;
3011 case YANG_DEFAULT:
David Sedlák6542aed2019-08-14 10:47:43 +02003012 case YANG_ERROR_APP_TAG:
3013 case YANG_KEY:
3014 case YANG_PRESENCE:
3015 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 +02003016 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003017 case YANG_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02003018 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003019 break;
3020 case YANG_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02003021 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003022 break;
David Sedlák43801c92019-08-05 15:58:54 +02003023 case YANG_ENUM:
3024 ret = yin_parse_enum(ctx, attrs, data, (struct lysp_type *)subelem->dest);
3025 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003026 case YANG_ERROR_MESSAGE:
David Sedlákdf2691f2019-08-15 13:32:27 +02003027 ret = yin_parse_err_msg(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003028 break;
3029 case YANG_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003030 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003031 break;
3032 case YANG_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02003033 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003034 break;
3035 case YANG_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02003036 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003037 break;
3038 case YANG_GROUPING:
David Sedlák6881b512019-08-13 12:52:00 +02003039 ret = yin_parse_grouping(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003040 break;
3041 case YANG_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02003042 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003043 break;
3044 case YANG_IF_FEATURE:
David Sedlák6542aed2019-08-14 10:47:43 +02003045 case YANG_UNITS:
3046 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 +02003047 break;
3048 case YANG_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02003049 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003050 break;
3051 case YANG_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02003052 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003053 break;
3054 case YANG_INPUT:
David Sedlák05404f62019-07-24 14:11:53 +02003055 case YANG_OUTPUT:
3056 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003057 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003058 case YANG_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02003059 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003060 break;
3061 case YANG_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02003062 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003063 break;
3064 case YANG_LENGTH:
David Sedlák6542aed2019-08-14 10:47:43 +02003065 ret = yin_parse_length(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003066 break;
3067 case YANG_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02003068 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003069 break;
3070 case YANG_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02003071 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003072 break;
3073 case YANG_MAX_ELEMENTS:
David Sedlákd6e56892019-07-01 15:40:24 +02003074 case YANG_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02003075 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003076 break;
3077 case YANG_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02003078 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003079 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003080 case YANG_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02003081 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003082 break;
3083 case YANG_NAMESPACE:
David Sedlák6542aed2019-08-14 10:47:43 +02003084 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 +02003085 break;
3086 case YANG_NOTIFICATION:
David Sedlák6881b512019-08-13 12:52:00 +02003087 ret = yin_parse_notification(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003088 break;
3089 case YANG_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02003090 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003091 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003092 case YANG_PATH:
David Sedlák6542aed2019-08-14 10:47:43 +02003093 ret = yin_parse_path(ctx, attrs, data, kw, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003094 break;
3095 case YANG_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02003096 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003097 break;
David Sedlák5545f5d2019-07-11 11:55:16 +02003098 case YANG_VALUE:
David Sedlákd6e56892019-07-01 15:40:24 +02003099 case YANG_POSITION:
David Sedlákdf2691f2019-08-15 13:32:27 +02003100 ret = yin_parse_value_pos(ctx, attrs, data, kw, (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003101 break;
3102 case YANG_PREFIX:
David Sedlák6542aed2019-08-14 10:47:43 +02003103 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 +02003104 break;
3105 case YANG_RANGE:
David Sedlák6542aed2019-08-14 10:47:43 +02003106 ret = yin_parse_range(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003107 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003108 case YANG_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02003109 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003110 break;
3111 case YANG_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02003112 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003113 break;
3114 case YANG_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02003115 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003116 break;
3117 case YANG_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02003118 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003119 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003120 case YANG_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02003121 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003122 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003123 case YANG_TYPE:
David Sedlák6542aed2019-08-14 10:47:43 +02003124 ret = yin_parse_type(ctx, attrs, data, current_element, subelem);
David Sedlákd6e56892019-07-01 15:40:24 +02003125 break;
3126 case YANG_TYPEDEF:
David Sedlák6881b512019-08-13 12:52:00 +02003127 ret = yin_parse_typedef(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003128 break;
3129 case YANG_UNIQUE:
David Sedlák6542aed2019-08-14 10:47:43 +02003130 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 +02003131 break;
3132 case YANG_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02003133 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003134 break;
David Sedlákd6e56892019-07-01 15:40:24 +02003135 case YANG_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02003136 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02003137 break;
3138 case YANG_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02003139 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02003140 break;
3141 case YANG_YIN_ELEMENT:
David Sedlákdf2691f2019-08-15 13:32:27 +02003142 ret = yin_parse_yin_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02003143 break;
3144 case YIN_TEXT:
David Sedlák3ffbc522019-07-02 17:49:28 +02003145 case YIN_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02003146 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02003147 break;
3148 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02003149 LOGINT(ctx->xml_ctx.ctx);
David Sedlákbf8a2b72019-08-14 16:48:10 +02003150 ret = LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02003151 }
David Sedlák3ffbc522019-07-02 17:49:28 +02003152 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02003153 FREE_ARRAY(ctx, attrs, free_arg_rec);
3154 attrs = NULL;
3155 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02003156 }
3157 } else {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003158 LY_CHECK_RET(ret);
David Sedlákd6e56892019-07-01 15:40:24 +02003159 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02003160 /* save text content, if text_content isn't set, it's just ignored */
David Sedlákc5b20842019-08-13 10:18:31 +02003161 /* no resources are allocated in this branch, no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02003162 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02003163 if (text_content) {
David Sedlák169cc522019-08-15 13:23:45 +02003164 INSERT_STRING(ctx->xml_ctx.ctx, *text_content, dynamic, out, out_len);
3165 LY_CHECK_RET(!*text_content, LY_EMEM);
David Sedlák3ffbc522019-07-02 17:49:28 +02003166 }
David Sedlákd6e56892019-07-01 15:40:24 +02003167 /* load closing element */
David Sedlákc5b20842019-08-13 10:18:31 +02003168 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákd6e56892019-07-01 15:40:24 +02003169 }
3170 }
David Sedlák8b754462019-07-25 16:22:13 +02003171 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3172 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003173
3174cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02003175 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02003176 return ret;
3177}
3178
David Sedlák619db942019-07-03 14:47:30 +02003179LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02003180yin_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 +02003181 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003182{
3183 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003184 char *out;
3185 const char *name, *prefix;
3186 size_t out_len, prefix_len, name_len;
3187 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003188 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003189 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
3190 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003191
David Sedlákda8ffa32019-07-08 14:17:10 +02003192 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003193
3194 e->yin = 0;
3195 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02003196 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02003197 e->insubstmt = subelem;
3198 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003199 e->yin |= LYS_YIN;
3200
David Sedlákb1a78352019-06-28 16:16:29 +02003201 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02003202 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02003203 if (!iter->prefix) {
3204 new_subelem = calloc(1, sizeof(*new_subelem));
3205 if (!e->child) {
3206 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003207 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003208 last_subelem->next = new_subelem;
3209 }
3210 last_subelem = new_subelem;
3211
3212 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003213 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
David Sedlák169cc522019-08-15 13:23:45 +02003214 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3215
3216 INSERT_STRING(ctx->xml_ctx.ctx, last_subelem->arg, iter->dynamic_content, iter->content, iter->content_len);
3217 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003218 }
3219 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003220
David Sedlákf250ecf2019-07-01 11:02:05 +02003221 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003222 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3223 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003224 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003225 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3226 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02003227 if (!name) {
3228 /* end of extension instance reached */
3229 break;
3230 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003231 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02003232 if (!e->child) {
3233 e->child = new_subelem;
3234 } else {
3235 last_subelem->next = new_subelem;
3236 }
3237 last_subelem = new_subelem;
3238 }
David Sedlák555c7202019-07-04 12:14:12 +02003239 } else {
David Sedlák169cc522019-08-15 13:23:45 +02003240 if (out_len != 0) {
3241 /* save text content */
3242 LY_CHECK_RET(ret);
3243
3244 INSERT_STRING(ctx->xml_ctx.ctx, e->argument, dynamic, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02003245 LY_CHECK_RET(!e->argument, LY_EMEM);
David Sedlák169cc522019-08-15 13:23:45 +02003246
3247 /* load closing element */
3248 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
3249 LY_CHECK_RET(name, LY_EINT);
David Sedlák555c7202019-07-04 12:14:12 +02003250 }
David Sedlákb1a78352019-06-28 16:16:29 +02003251 }
David Sedlákb1a78352019-06-28 16:16:29 +02003252 }
3253
3254 return LY_SUCCESS;
3255}
3256
3257LY_ERR
David Sedlák4ffcec82019-07-25 15:10:21 +02003258yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char **data,
3259 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02003260{
3261 LY_ERR ret = LY_SUCCESS;
3262 const char *temp_prefix, *temp_name;
3263 char *out = NULL;
David Sedlák4ffcec82019-07-25 15:10:21 +02003264 size_t out_len, temp_name_len, temp_prefix_len, prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02003265 int dynamic;
3266 struct yin_arg_record *subelem_args = NULL;
3267 struct lysp_stmt *last = NULL, *new = NULL;
3268
3269 /* allocate new structure for element */
3270 *element = calloc(1, sizeof(**element));
David Sedlákda8ffa32019-07-08 14:17:10 +02003271 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, name, name_len);
3272 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003273
3274 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +02003275 /* load attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +02003276 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákb1a78352019-06-28 16:16:29 +02003277 /* add new element to linked-list */
3278 new = calloc(1, sizeof(*last));
David Sedlákda8ffa32019-07-08 14:17:10 +02003279 LY_CHECK_ERR_GOTO(ret, LOGMEM(ctx->xml_ctx.ctx), err);
David Sedlákb1a78352019-06-28 16:16:29 +02003280 if (!(*element)->child) {
3281 /* save first */
3282 (*element)->child = new;
3283 } else {
3284 last->next = new;
3285 }
3286 last = new;
3287
3288 last->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003289 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 +02003290 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003291 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003292 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003293 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
3294 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003295 /* attributes with prefix are ignored */
3296 if (!temp_prefix) {
David Sedlák169cc522019-08-15 13:23:45 +02003297 INSERT_STRING(ctx->xml_ctx.ctx, last->arg, dynamic, out, out_len);
3298 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003299 }
3300 }
3301
3302 /* parse content of element */
David Sedlákda8ffa32019-07-08 14:17:10 +02003303 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003304 if (ret == LY_EINVAL) {
David Sedlák169cc522019-08-15 13:23:45 +02003305 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003306 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákb1a78352019-06-28 16:16:29 +02003307 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003308 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 +02003309 LY_CHECK_GOTO(ret, err);
3310 if (!name) {
3311 /* end of element reached */
3312 break;
3313 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003314 ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, data, &last->next);
David Sedlákb1a78352019-06-28 16:16:29 +02003315 LY_CHECK_GOTO(ret, err);
3316 last = last->next;
3317 }
3318 } else {
David Sedlák169cc522019-08-15 13:23:45 +02003319 LY_CHECK_RET(ret);
David Sedlákb1a78352019-06-28 16:16:29 +02003320 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +02003321 if (out_len != 0) {
David Sedlák169cc522019-08-15 13:23:45 +02003322 INSERT_STRING(ctx->xml_ctx.ctx, (*element)->arg, dynamic, out, out_len);
3323 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003324 }
David Sedlák169cc522019-08-15 13:23:45 +02003325
David Sedlákb1a78352019-06-28 16:16:29 +02003326 /* read closing tag */
David Sedlákda8ffa32019-07-08 14:17:10 +02003327 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 +02003328 LY_CHECK_GOTO(ret, err);
3329 }
3330
David Sedlákb1a78352019-06-28 16:16:29 +02003331err:
David Sedlákda8ffa32019-07-08 14:17:10 +02003332 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003333 return ret;
3334}
3335
3336LY_ERR
David Sedlák4f03b932019-07-26 13:01:47 +02003337yin_parse_mod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003338{
David Sedlák81497a32019-08-13 16:56:26 +02003339 LY_ERR ret = LY_SUCCESS;
3340 struct yin_subelement *subelems = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003341
David Sedlák81497a32019-08-13 16:56:26 +02003342 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, YANG_MODULE));
3343 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
3344 YANG_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3345 YANG_ANYXML, &mod->data, 0,
3346 YANG_AUGMENT, &mod->augments, 0,
3347 YANG_CHOICE, &mod->data, 0,
3348 YANG_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3349 YANG_CONTAINER, &mod->data, 0,
3350 YANG_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3351 YANG_DEVIATION, &mod->deviations, 0,
3352 YANG_EXTENSION, &mod->extensions, 0,
3353 YANG_FEATURE, &mod->features, 0,
3354 YANG_GROUPING, &mod->groupings, 0,
3355 YANG_IDENTITY, &mod->identities, 0,
3356 YANG_IMPORT, mod->mod->prefix, &mod->imports, 0,
3357 YANG_INCLUDE, mod->mod->name, &mod->includes, 0,
3358 YANG_LEAF, &mod->data, 0,
3359 YANG_LEAF_LIST, &mod->data, 0,
3360 YANG_LIST, &mod->data, 0,
3361 YANG_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3362 YANG_NOTIFICATION, &mod->notifs, 0,
3363 YANG_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3364 YANG_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3365 YANG_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3366 YANG_REVISION, &mod->revs, 0,
3367 YANG_RPC, &mod->rpcs, 0,
3368 YANG_TYPEDEF, &mod->typedefs, 0,
3369 YANG_USES, &mod->data, 0,
3370 YANG_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3371 YANG_CUSTOM, NULL, 0
3372 ));
3373
3374 ret = yin_parse_content(ctx, subelems, 28, data, YANG_MODULE, NULL, &mod->exts);
3375 subelems_deallocator(28, subelems);
3376
3377 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003378}
3379
3380LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003381yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3382{
David Sedlák81497a32019-08-13 16:56:26 +02003383 LY_ERR ret = LY_SUCCESS;
3384 struct yin_subelement *subelems = NULL;
David Sedlák298ff6d2019-07-26 14:29:03 +02003385
David Sedlák81497a32019-08-13 16:56:26 +02003386 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, YANG_SUBMODULE));
3387 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
3388 YANG_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3389 YANG_ANYXML, &submod->data, 0,
3390 YANG_AUGMENT, &submod->augments, 0,
3391 YANG_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3392 YANG_CHOICE, &submod->data, 0,
3393 YANG_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3394 YANG_CONTAINER, &submod->data, 0,
3395 YANG_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3396 YANG_DEVIATION, &submod->deviations, 0,
3397 YANG_EXTENSION, &submod->extensions, 0,
3398 YANG_FEATURE, &submod->features, 0,
3399 YANG_GROUPING, &submod->groupings, 0,
3400 YANG_IDENTITY, &submod->identities, 0,
3401 YANG_IMPORT, submod->prefix, &submod->imports, 0,
3402 YANG_INCLUDE, submod->name, &submod->includes, 0,
3403 YANG_LEAF, &submod->data, 0,
3404 YANG_LEAF_LIST, &submod->data, 0,
3405 YANG_LIST, &submod->data, 0,
3406 YANG_NOTIFICATION, &submod->notifs, 0,
3407 YANG_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3408 YANG_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3409 YANG_REVISION, &submod->revs, 0,
3410 YANG_RPC, &submod->rpcs, 0,
3411 YANG_TYPEDEF, &submod->typedefs, 0,
3412 YANG_USES, &submod->data, 0,
3413 YANG_YANG_VERSION, &submod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3414 YANG_CUSTOM, NULL, 0
3415 ));
3416
3417 ret = yin_parse_content(ctx, subelems, 27, data, YANG_SUBMODULE, NULL, &submod->exts);
3418 subelems_deallocator(27, subelems);
3419
3420 return ret;
David Sedlák298ff6d2019-07-26 14:29:03 +02003421}
3422
3423LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02003424yin_parse_submodule(struct yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, struct lys_parser_ctx *main_ctx, const char *data, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003425{
3426 enum yang_keyword kw = YANG_NONE;
3427 LY_ERR ret = LY_SUCCESS;
3428 const char *prefix, *name;
3429 size_t prefix_len, name_len;
3430 struct yin_arg_record *attrs = NULL;
3431 struct lysp_submodule *mod_p = NULL;
3432
3433 /* create context */
3434 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003435 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003436 (*yin_ctx)->xml_ctx.ctx = ctx;
3437 (*yin_ctx)->xml_ctx.line = 1;
3438
David Sedlák1b623122019-08-05 15:27:49 +02003439 /* map the typedefs and groupings list from main context to the submodule's context */
3440 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3441 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3442
David Sedlák8985a142019-07-31 16:43:06 +02003443 /* check submodule */
3444 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3445 LY_CHECK_GOTO(ret, cleanup);
3446 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3447 LY_CHECK_GOTO(ret, cleanup);
3448 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
3449
3450 if (kw == YANG_MODULE) {
3451 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3452 ret = LY_EINVAL;
3453 goto cleanup;
3454 } else if (kw != YANG_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003455 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003456 ret = LY_EVALID;
3457 goto cleanup;
3458 }
3459
3460 mod_p = calloc(1, sizeof *mod_p);
3461 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3462 mod_p->parsing = 1;
3463
3464 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3465 LY_CHECK_GOTO(ret, cleanup);
3466
David Sedlák6d781b62019-08-02 15:22:52 +02003467 name = NULL;
David Sedlákbf8a2b72019-08-14 16:48:10 +02003468 /* skip possible trailing whitespaces at end of the input */
3469 while(*data && isspace(*data)) {
3470 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003471 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003472 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003473 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, data, strlen(data) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003474 ret = LY_EVALID;
3475 goto cleanup;
3476 }
3477
David Sedlák8985a142019-07-31 16:43:06 +02003478 mod_p->parsing = 0;
3479 *submod = mod_p;
3480
3481cleanup:
3482 if (ret) {
3483 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003484 yin_parser_ctx_free(*yin_ctx);
3485 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003486 }
3487
3488 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3489 return ret;
3490}
3491
3492LY_ERR
3493yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003494{
David Sedláke4889912018-11-02 09:52:40 +01003495 LY_ERR ret = LY_SUCCESS;
3496 enum yang_keyword kw = YANG_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003497 struct lysp_module *mod_p = NULL;
3498 const char *prefix, *name;
3499 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003500 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003501
David Sedlák8985a142019-07-31 16:43:06 +02003502 /* create context */
3503 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003504 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003505 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
3506 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003507
David Sedlák8985a142019-07-31 16:43:06 +02003508 /* check module */
3509 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003510 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003511 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003512 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003513 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
David Sedláke4889912018-11-02 09:52:40 +01003514 if (kw == YANG_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003515 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 +01003516 ret = LY_EINVAL;
3517 goto cleanup;
3518 } else if (kw != YANG_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003519 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003520 ret = LY_EVALID;
3521 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003522 }
3523
David Sedlák3017da42019-02-15 09:48:04 +01003524 /* allocate module */
3525 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003526 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003527 mod_p->mod = mod;
3528 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003529
David Sedlák00250342019-06-21 14:19:39 +02003530 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003531 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003532 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003533
David Sedlákbf8a2b72019-08-14 16:48:10 +02003534 name = NULL;
3535 /* skip possible trailing whitespaces at end of the input */
3536 while(*data && isspace(*data)) {
3537 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003538 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003539 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003540 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 +02003541 ret = LY_EVALID;
3542 goto cleanup;
3543 }
3544
David Sedlák3017da42019-02-15 09:48:04 +01003545 mod_p->parsing = 0;
3546 mod->parsed = mod_p;
3547
3548cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003549 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003550 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003551 yin_parser_ctx_free(*yin_ctx);
3552 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003553 }
David Sedlák8985a142019-07-31 16:43:06 +02003554 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003555 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003556}