blob: b33b33feb996cbec8c958773bc689158b331acc3 [file] [log] [blame]
David Sedlákf824ad52018-10-14 23:58:15 +02001/**
2 * @file parser_yin.c
3 * @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
David Sedlák3b4db242018-10-19 16:11:01 +02004 * @brief YIN parser.
5 *
David Sedlákb1ce3f82019-06-05 14:37:26 +02006 * Copyright (c) 2015 - 2019 CESNET, z.s.p.o.
David Sedlák3b4db242018-10-19 16:11:01 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
David Sedlákf824ad52018-10-14 23:58:15 +020013 */
David Sedlákecf5eb82019-06-03 14:12:44 +020014#include "common.h"
15
David Sedlák3ffbc522019-07-02 17:49:28 +020016#include <assert.h>
David Sedlák3b4db242018-10-19 16:11:01 +020017#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
David Sedlák872c7b42018-10-26 13:15:20 +020020#include <string.h>
David Sedlákd6e56892019-07-01 15:40:24 +020021#include <stdbool.h>
David Sedlák5545f5d2019-07-11 11:55:16 +020022#include <errno.h>
David Sedlákf75d55e2019-07-12 16:52:50 +020023#include <ctype.h>
David Sedlák81497a32019-08-13 16:56:26 +020024#include <stdarg.h>
David Sedlákf824ad52018-10-14 23:58:15 +020025
David Sedlákf824ad52018-10-14 23:58:15 +020026#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020027#include "dict.h"
David Sedlák3b4db242018-10-19 16:11:01 +020028#include "xml.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020029#include "tree.h"
30#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020031#include "tree_schema_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020032#include "parser_yin.h"
David Sedlák00250342019-06-21 14:19:39 +020033
David Sedlák2b214ac2019-06-06 16:11:03 +020034/**
35 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020036 *
David Sedlák2b214ac2019-06-06 16:11:03 +020037 * @param ns Namespace URI to check.
38 *
39 * @return true if ns equals YIN_NS_URI false otherwise.
40 */
41#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
42
David Sedlákf6251182019-06-06 10:22:13 +020043const char *const yin_attr_list[] = {
44 [YIN_ARG_NAME] = "name",
45 [YIN_ARG_TARGET_NODE] = "target-node",
46 [YIN_ARG_MODULE] = "module",
47 [YIN_ARG_VALUE] = "value",
48 [YIN_ARG_TEXT] = "text",
49 [YIN_ARG_CONDITION] = "condition",
50 [YIN_ARG_URI] = "uri",
51 [YIN_ARG_DATE] = "date",
52 [YIN_ARG_TAG] = "tag",
David Sedlák071f7662019-09-12 02:02:51 +020053 [YIN_ARG_NONE] = "none",
David Sedlákf6251182019-06-06 10:22:13 +020054};
55
Radek Krejcid6b76452019-09-03 17:03:03 +020056enum ly_stmt
Michal Vaskob36053d2020-03-26 15:49:30 +010057yin_match_keyword(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejcid6b76452019-09-03 17:03:03 +020058 const char *prefix, size_t prefix_len, enum ly_stmt parrent)
David Sedlák1bccdfa2019-06-17 15:55:27 +020059{
David Sedlák8f7a1172019-06-20 14:42:18 +020060 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +020061 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020062 const struct lyxml_ns *ns = NULL;
63
64 if (!name || name_len == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +020065 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +020066 }
67
Michal Vaskob36053d2020-03-26 15:49:30 +010068 ns = lyxml_ns_get(ctx->xmlctx, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +020069 if (ns) {
70 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +020071 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +020072 }
73 } else {
74 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +020075 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020076 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020077
David Sedlák8f7a1172019-06-20 14:42:18 +020078 start = name;
79 kw = lysp_match_kw(NULL, &name);
80
81 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +020082 /* this is done because of collision in yang statement value and yang argument mapped to yin element value */
Radek Krejcid6b76452019-09-03 17:03:03 +020083 if (kw == LY_STMT_VALUE && parrent == LY_STMT_ERROR_MESSAGE) {
84 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +020085 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020086 return kw;
87 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020088 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +020089 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +020090 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +020091 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +020092 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020093 }
94}
95
David Sedlákc5b20842019-08-13 10:18:31 +020096enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +020097yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020098{
David Sedlákc5b20842019-08-13 10:18:31 +020099 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200100 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200101 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200102
David Sedlák94de2aa2019-02-15 12:42:11 +0100103#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
104#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100105#define IF_ARG_PREFIX_END }
106
David Sedlák1c8b2702019-02-22 11:03:02 +0100107 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100108 case 'c':
109 already_read += 1;
110 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200111 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200112
David Sedlák94de2aa2019-02-15 12:42:11 +0100113 case 'd':
114 already_read += 1;
115 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200116 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200117
David Sedlák94de2aa2019-02-15 12:42:11 +0100118 case 'm':
119 already_read += 1;
120 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200121 break;
122
David Sedlák94de2aa2019-02-15 12:42:11 +0100123 case 'n':
124 already_read += 1;
125 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200126 break;
127
David Sedlák94de2aa2019-02-15 12:42:11 +0100128 case 't':
129 already_read += 1;
130 IF_ARG_PREFIX("a", 1)
131 IF_ARG("g", 1, YIN_ARG_TAG)
132 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
133 IF_ARG_PREFIX_END
134 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200135 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200136
David Sedlák94de2aa2019-02-15 12:42:11 +0100137 case 'u':
138 already_read += 1;
139 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200140 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200141
David Sedlák94de2aa2019-02-15 12:42:11 +0100142 case 'v':
143 already_read += 1;
144 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200145 break;
146 }
147
David Sedlákc10e7902018-12-17 02:17:59 +0100148 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200149 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200150 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200151 }
152
David Sedlák18730132019-03-15 15:51:34 +0100153#undef IF_ARG
154#undef IF_ARG_PREFIX
155#undef IF_ARG_PREFIX_END
156
David Sedlák872c7b42018-10-26 13:15:20 +0200157 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200158}
159
Radek Krejcid6b76452019-09-03 17:03:03 +0200160#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
161 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
162 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
163 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200164
Radek Krejcid6b76452019-09-03 17:03:03 +0200165#define HAS_META(kw) (IS_NODE_ELEM(kw) || kw == LY_STMT_IMPORT || kw == LY_STMT_INCLUDE || kw == LY_STMT_INPUT || kw == LY_STMT_OUTPUT)
David Sedlák81497a32019-08-13 16:56:26 +0200166
David Sedlák26ea1432019-08-14 13:42:23 +0200167/**
168 * @brief Free subelems information allocated on heap.
169 *
170 * @param[in] count Size of subelems array.
171 * @param[in] subelems Subelems array to free.
172 */
David Sedlák81497a32019-08-13 16:56:26 +0200173static void
174subelems_deallocator(size_t count, struct yin_subelement *subelems)
175{
176 for(size_t i = 0; i < count; ++i) {
177 if (HAS_META(subelems[i].type)) {
178 free(subelems[i].dest);
179 }
180 }
181
182 free(subelems);
183}
184
David Sedlák26ea1432019-08-14 13:42:23 +0200185/**
186 * @brief Allocate subelems information on heap.
187 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200188 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200189 * @param[in] count Number of subelements.
190 * @param[in] parent Parent node if any.
191 * @param[out] result Allocated subelems array.
192 *
193 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
194 */
David Sedlák81497a32019-08-13 16:56:26 +0200195static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100196subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
David Sedlák81497a32019-08-13 16:56:26 +0200197 struct yin_subelement **result, ...)
198{
199 va_list ap;
200
201 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200202 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200203
204 va_start(ap, result);
205 for (size_t i = 0; i < count; ++i) {
206 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200207 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200208 /* DEST */
209 if (IS_NODE_ELEM((*result)[i].type)) {
210 struct tree_node_meta *node_meta = NULL;
211 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200212 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200213 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200214 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200215 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200216 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200217 struct import_meta *imp_meta = NULL;
218 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200219 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200220 imp_meta->prefix = va_arg(ap, const char *);
221 imp_meta->imports = va_arg(ap, struct lysp_import **);
222 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200223 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200224 struct include_meta *inc_meta = NULL;
225 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200226 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200227 inc_meta->name = va_arg(ap, const char *);
228 inc_meta->includes = va_arg(ap, struct lysp_include **);
229 (*result)[i].dest = inc_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200230 } else if ((*result)[i].type == LY_STMT_INPUT || (*result)[i].type == LY_STMT_OUTPUT) {
David Sedlák81497a32019-08-13 16:56:26 +0200231 struct inout_meta *inout_meta = NULL;
232 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200233 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200234 inout_meta->parent = parent;
235 inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
236 (*result)[i].dest = inout_meta;
237 } else {
238 (*result)[i].dest = va_arg(ap, void *);
239 }
240 /* FLAGS */
241 (*result)[i].flags = va_arg(ap, int);
242 }
243 va_end(ap);
244
245 return LY_SUCCESS;
246
David Sedlákbf8a2b72019-08-14 16:48:10 +0200247mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200248 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100249 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200250 return LY_EMEM;
251}
252
David Sedlák8f7a1172019-06-20 14:42:18 +0200253LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100254yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200255{
256 int prefix = 0;
257 unsigned int c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100258 size_t utf8_char_len, already_read = 0;
259 const char *val;
260
261 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
262
263 val = ctx->xmlctx->value;
264 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200265 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
266 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
267 already_read += utf8_char_len;
Michal Vaskob36053d2020-03-26 15:49:30 +0100268 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200269
270 switch (val_type) {
271 case Y_IDENTIF_ARG:
272 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
273 break;
274 case Y_PREF_IDENTIF_ARG:
275 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
276 break;
277 case Y_STR_ARG:
278 case Y_MAYBE_STR_ARG:
279 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
280 break;
281 }
282 }
283
284 return LY_SUCCESS;
285}
286
David Sedlákb4e44562019-07-04 15:42:12 +0200287/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100288 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200289 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200290 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200291 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
292 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200293 * @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 +0200294 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200295 * @param[in] current_element Identification of current element, used for logging.
296 *
297 * @return LY_ERR values.
298 */
299static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100300yin_parse_attribute(struct lys_yin_parser_ctx *ctx, enum yin_argument arg_type, const char **arg_val, enum yang_arg val_type,
301 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200302{
David Sedlákc5b20842019-08-13 10:18:31 +0200303 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200304 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200305
David Sedlák1bccdfa2019-06-17 15:55:27 +0200306 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100307 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200308 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100309 if (!ctx->xmlctx->prefix) {
310 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200311 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100312 /* skip it */
313 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200314 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200315 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
David Sedlák292763b2019-07-09 11:10:53 +0200316 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200317 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100318
319 /* go to value */
320 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
321 LY_CHECK_RET(yin_validate_value(ctx, val_type));
322 *arg_val = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
David Sedlák169cc522019-08-15 13:23:45 +0200323 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200324 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100325 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
326 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200327 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200328 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100329 } else {
330 /* skip it */
331 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200332 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100333
334 /* next attribute */
335 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200336 }
337
David Sedlák292763b2019-07-09 11:10:53 +0200338 /* anything else than Y_MAYBE_STR_ARG is mandatory */
339 if (val_type != Y_MAYBE_STR_ARG && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100340 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
341 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200342 return LY_EVALID;
343 }
344
345 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200346}
347
David Sedlákd6e56892019-07-01 15:40:24 +0200348/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200349 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200350 *
351 * @param[in] type Type of wanted record.
352 * @param[in] array_size Size of array.
353 * @param[in] array Searched array.
354 *
355 * @return Pointer to desired record on success, NULL if element is not in the array.
356 */
David Sedlákb4e44562019-07-04 15:42:12 +0200357static struct yin_subelement *
Radek Krejci12b1c152019-09-05 16:20:48 +0200358get_record(enum ly_stmt type, size_t array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200359{
Radek Krejci12b1c152019-09-05 16:20:48 +0200360 for (unsigned int u = 0; u < array_size; ++u) {
361 if (array[u].type == type) {
362 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200363 }
364 }
David Sedlákd6e56892019-07-01 15:40:24 +0200365 return NULL;
366}
367
David Sedlákbba38e52019-07-09 15:20:01 +0200368/**
369 * @brief Helper function to check mandatory constraint of subelement.
370 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200371 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200372 * @param[in] subelem_info Array of information about subelements.
373 * @param[in] subelem_info_size Size of subelem_info array.
374 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
375 *
376 * @return LY_ERR values.
377 */
378static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100379yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200380 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200381{
David Sedlákb0faad82019-07-04 14:28:59 +0200382 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200383 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200384 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200385 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200386 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200387 return LY_EVALID;
388 }
389 }
390
391 return LY_SUCCESS;
392}
393
David Sedlákbba38e52019-07-09 15:20:01 +0200394/**
395 * @brief Helper function to check "first" constraint of subelement.
396 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200397 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200398 * @param[in] subelem_info Array of information about subelements.
399 * @param[in] subelem_info_size Size of subelem_info array.
400 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200401 * @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 +0200402 *
403 * @return LY_ERR values.
404 */
405static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100406yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200407 signed char subelem_info_size, enum ly_stmt current_element,
David Sedláke1a30302019-07-10 13:49:38 +0200408 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200409{
David Sedlákb0faad82019-07-04 14:28:59 +0200410 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200411 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200412 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
413 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200414 return LY_EVALID;
415 }
416 }
417
418 return LY_SUCCESS;
419}
420
David Sedlákbba38e52019-07-09 15:20:01 +0200421/**
David Sedlákb4e44562019-07-04 15:42:12 +0200422 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
423 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200424 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200425 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200426 * @param[in] kw Type of current element.
427 * @param[out] value Where value of attribute should be stored.
428 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200429 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200430 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200431 * @return LY_ERR values.
432 */
David Sedlákb4e44562019-07-04 15:42:12 +0200433static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100434yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
435 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200436{
Michal Vaskob36053d2020-03-26 15:49:30 +0100437 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
438 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200439 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200440 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200441 };
David Sedlákb4e44562019-07-04 15:42:12 +0200442
Michal Vaskob36053d2020-03-26 15:49:30 +0100443 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200444}
445
446/**
David Sedlák6542aed2019-08-14 10:47:43 +0200447 * @brief Parse path element.
448 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200449 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200450 * @param[in] kw Type of current element.
451 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200452 * @return LY_ERR values.
453 */
454static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100455yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200456{
Michal Vaskob36053d2020-03-26 15:49:30 +0100457 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, &type->path, YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200458 type->flags |= LYS_SET_PATH;
459
460 return LY_SUCCESS;
461}
462
463/**
David Sedlákd3983112019-07-12 11:20:56 +0200464 * @brief Parse pattern element.
465 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200466 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200467 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200468 * @return LY_ERR values.
469 */
470static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100471yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200472{
473 const char *real_value = NULL;
474 char *saved_value = NULL;
475 struct lysp_restr *restr;
476
Michal Vaskob36053d2020-03-26 15:49:30 +0100477 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
478 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
479 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &real_value, Y_STR_ARG, LY_STMT_PATTERN));
David Sedlákd3983112019-07-12 11:20:56 +0200480 size_t len = strlen(real_value);
481
482 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100483 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200484 memmove(saved_value + 1, real_value, len);
Michal Vaskob36053d2020-03-26 15:49:30 +0100485 FREE_STRING(ctx->xmlctx->ctx, real_value);
David Sedlákd3983112019-07-12 11:20:56 +0200486 saved_value[0] = 0x06;
487 saved_value[len + 1] = '\0';
Michal Vaskob36053d2020-03-26 15:49:30 +0100488 restr->arg = lydict_insert_zc(ctx->xmlctx->ctx, saved_value);
489 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200490 type->flags |= LYS_SET_PATTERN;
491
492 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200493 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
494 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
495 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
496 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
497 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
498 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákd3983112019-07-12 11:20:56 +0200499 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100500 return yin_parse_content(ctx, subelems, 6, LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200501}
502
David Sedlákc5b20842019-08-13 10:18:31 +0200503/**
504 * @brief Parse fraction-digits element.
505 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200506 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200507 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200508 * @return LY_ERR values.
509 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200510static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100511yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200512{
513 const char *temp_val = NULL;
514 char *ptr;
515 unsigned long int num;
516
Michal Vaskob36053d2020-03-26 15:49:30 +0100517 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
518 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_FRACTION_DIGITS));
David Sedlákf75d55e2019-07-12 16:52:50 +0200519
520 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200521 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100522 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200523 return LY_EVALID;
524 }
525
526 errno = 0;
527 num = strtoul(temp_val, &ptr, 10);
528 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200529 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100530 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200531 return LY_EVALID;
532 }
533 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200534 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100535 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200536 return LY_EVALID;
537 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100538 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200539 type->fraction_digits = num;
540 type->flags |= LYS_SET_FRDIGITS;
541 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200542 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200543 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100544 return yin_parse_content(ctx, subelems, 1, LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200545}
546
David Sedlák07869a52019-07-12 14:28:19 +0200547/**
David Sedlák43801c92019-08-05 15:58:54 +0200548 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200549 *
550 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200551 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200552 * @return LY_ERR values.
553 */
David Sedlákca36c422019-07-12 12:47:55 +0200554static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100555yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200556{
David Sedlák07869a52019-07-12 14:28:19 +0200557 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200558
Michal Vaskob36053d2020-03-26 15:49:30 +0100559 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200560 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100561 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
562 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_STR_ARG, LY_STMT_ENUM));
David Sedlák43801c92019-08-05 15:58:54 +0200563 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100564 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200565 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200566
567 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200568 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
569 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
570 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
571 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
572 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
573 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákca36c422019-07-12 12:47:55 +0200574 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100575 return yin_parse_content(ctx, subelems, 6, LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200576}
577
578/**
579 * @brief Parse bit element.
580 *
581 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200582 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200583 * @return LY_ERR values.
584 */
585static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100586yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200587{
588 struct lysp_type_enum *en;
589
Michal Vaskob36053d2020-03-26 15:49:30 +0100590 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200591 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100592 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
593 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, LY_STMT_BIT));
David Sedlák43801c92019-08-05 15:58:54 +0200594 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
595
596 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200597 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
598 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
599 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
600 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
601 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
602 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák43801c92019-08-05 15:58:54 +0200603 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100604 return yin_parse_content(ctx, subelems, 6, LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200605}
606
David Sedlákd3983112019-07-12 11:20:56 +0200607/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200608 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
609 * more instances, such as base or if-feature.
610 *
611 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200612 * @param[in] kw Type of current element.
613 * @param[out] values Parsed values to add to.
614 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200615 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200616 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200617 * @return LY_ERR values.
618 */
619static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100620yin_parse_simple_elements(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char ***values, enum yin_argument arg_type,
621 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200622{
623 const char **value;
Michal Vaskob36053d2020-03-26 15:49:30 +0100624 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200625 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200626 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200627 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200628 };
629
Michal Vaskob36053d2020-03-26 15:49:30 +0100630 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
631 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200632
Michal Vaskob36053d2020-03-26 15:49:30 +0100633 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200634}
635
636/**
David Sedlák6542aed2019-08-14 10:47:43 +0200637 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
638 *
639 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200640 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200641 * @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 +0200642 * @param[in] arg_type Expected type of attribute.
643 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200644 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200645 * @return LY_ERR values.
646 */
647static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100648yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
649 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200650{
651 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100652 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200653 arg_type, arg_val_type, exts));
654 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100655 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200656 arg_type, arg_val_type, exts));
657 }
658
659 return LY_SUCCESS;
660}
661
662/**
663 * @brief Parse base element.
664 *
665 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200666 * @param[in] parent Identification of parent element.
667 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200668 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200669 * @return LY_ERR values.
670 */
671static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100672yin_parse_base(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, void *dest, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200673{
674 struct lysp_type *type = NULL;
675
Radek Krejcid6b76452019-09-03 17:03:03 +0200676 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200677 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100678 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
David Sedlák6542aed2019-08-14 10:47:43 +0200679 Y_PREF_IDENTIF_ARG, exts));
680 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200681 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100682 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200683 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
684 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100685 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200686 return LY_EINT;
687 }
688
689 return LY_SUCCESS;
690}
691
692/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200693 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200694 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200695 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100696 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200697 * @return LY_ERR values.
698 */
699static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100700yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200701{
702 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200703 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200704 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200705 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200706
707 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100708 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
709 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_REQUIRE_INSTANCE));
David Sedlákcf5569a2019-07-11 13:31:34 +0200710 if (strcmp(temp_val, "true") == 0) {
711 type->require_instance = 1;
712 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200713 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
714 "require-instance", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +0100715 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200716 return LY_EVALID;
717 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100718 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200719
Michal Vaskob36053d2020-03-26 15:49:30 +0100720 return yin_parse_content(ctx, subelems, 1, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200721}
722
723/**
David Sedlákce77bf52019-07-11 16:59:31 +0200724 * @brief Parse modifier element.
725 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200726 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200727 * @param[in,out] pat Value to write to.
728 * @param[in,out] exts Extension instances to add to.
729 *
730 * @return LY_ERR values.
731 */
732static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100733yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200734{
David Sedlákd3983112019-07-12 11:20:56 +0200735 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200736 const char *temp_val;
737 char *modified_val;
738 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200739 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákce77bf52019-07-11 16:59:31 +0200740 };
741
Michal Vaskob36053d2020-03-26 15:49:30 +0100742 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
743 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MODIFIER));
David Sedlákce77bf52019-07-11 16:59:31 +0200744 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200745 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
746 "modifier", "invert-match");
Michal Vaskob36053d2020-03-26 15:49:30 +0100747 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200748 return LY_EVALID;
749 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100750 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200751
752 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200753 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100754 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200755 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100756 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200757
758 /* modify the new value */
759 modified_val[0] = 0x15;
Michal Vaskob36053d2020-03-26 15:49:30 +0100760 *pat = lydict_insert_zc(ctx->xmlctx->ctx, modified_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200761
Michal Vaskob36053d2020-03-26 15:49:30 +0100762 return yin_parse_content(ctx, subelems, 1, LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200763}
764
765/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200766 * @brief Parse a restriction element (length, range or one instance of must).
767 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200768 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200769 * @param[in] restr_kw Identificaton of element that is being parsed, can be set to LY_STMT_MUST, LY_STMT_LENGTH or LY_STMT_RANGE.
David Sedlák6542aed2019-08-14 10:47:43 +0200770 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200771 */
772static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100773yin_parse_restriction(struct lys_yin_parser_ctx *ctx, enum ly_stmt restr_kw, struct lysp_restr *restr)
David Sedlákb7296dd2019-07-11 14:58:38 +0200774{
Radek Krejcid6b76452019-09-03 17:03:03 +0200775 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
David Sedlákb7296dd2019-07-11 14:58:38 +0200776 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200777 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
778 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
779 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
780 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
781 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200782 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200783 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200784 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200785
Michal Vaskob36053d2020-03-26 15:49:30 +0100786 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
787 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
788
789 return yin_parse_content(ctx, subelems, 5, restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200790}
791
792/**
David Sedlák6542aed2019-08-14 10:47:43 +0200793 * @brief Parse range element.
794 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200795 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200796 * @param[out] type Type structure to store parsed value and flags.
797 *
798 * @return LY_ERR values.
799 */
800static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100801yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200802{
803 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100804 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
805 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
David Sedlák6542aed2019-08-14 10:47:43 +0200806 type->flags |= LYS_SET_RANGE;
807
808 return LY_SUCCESS;
809}
810
811/**
812 * @brief Parse length element.
813 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200814 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200815 * @param[out] type Type structure to store parsed value and flags.
816 *
817 * @return LY_ERR values.
818 */
819static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100820yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200821{
822 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100823 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
824 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200825 type->flags |= LYS_SET_LENGTH;
826
827 return LY_SUCCESS;
828}
829
830/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200831 * @brief Parse must element.
832 *
833 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200834 * @param[in,out] restrs Restrictions to add to.
835 *
836 * @return LY_ERR values.
837 */
838static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100839yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200840{
841 struct lysp_restr *restr;
842
Michal Vaskob36053d2020-03-26 15:49:30 +0100843 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
844 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200845}
846
847/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200848 * @brief Parse position or value element.
849 *
850 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200851 * @param[in] kw Type of current element, can be set to LY_STMT_POSITION or LY_STMT_VALUE.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200852 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200853 *
854 * @return LY_ERR values.
855 */
856static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100857yin_parse_value_pos(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type_enum *enm)
David Sedlák5545f5d2019-07-11 11:55:16 +0200858{
Radek Krejcid6b76452019-09-03 17:03:03 +0200859 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +0200860 const char *temp_val = NULL;
861 char *ptr;
862 long int num;
863 unsigned long int unum;
864
865 /* set value flag */
866 enm->flags |= LYS_SET_VALUE;
867
868 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +0100869 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
870 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
David Sedlákae5378f2019-07-17 11:37:59 +0200871 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
Radek Krejcid6b76452019-09-03 17:03:03 +0200872 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200873 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 +0200874 goto error;
875 }
876
877 /* convert value */
878 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +0200879 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200880 num = strtol(temp_val, &ptr, 10);
881 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200882 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 +0200883 goto error;
884 }
885 } else {
886 unum = strtoul(temp_val, &ptr, 10);
887 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200888 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 +0200889 goto error;
890 }
891 }
892 /* check if whole argument value was converted */
893 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200894 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 +0200895 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200896 }
897 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +0200898 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 +0200899 goto error;
900 }
901 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +0200902 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200903 enm->value = num;
904 } else {
905 enm->value = unum;
906 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100907 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +0200908
909 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200910 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200911 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200912 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100913 return yin_parse_content(ctx, subelems, 1, kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +0200914
David Sedlákbf8a2b72019-08-14 16:48:10 +0200915error:
Michal Vaskob36053d2020-03-26 15:49:30 +0100916 FREE_STRING(ctx->xmlctx->ctx, temp_val);
917 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +0200918}
919
David Sedlák05404f62019-07-24 14:11:53 +0200920/**
921 * @brief Parse belongs-to element.
922 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200923 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +0200924 * @param[out] submod Structure of submodule that is being parsed.
925 * @param[in,out] exts Extension instances to add to.
926 *
927 * @return LY_ERR values
928 */
929static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100930yin_parse_belongs_to(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod, struct lysp_ext_instance **exts)
David Sedlák05404f62019-07-24 14:11:53 +0200931{
932 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200933 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
934 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák05404f62019-07-24 14:11:53 +0200935 };
David Sedlák05404f62019-07-24 14:11:53 +0200936
Michal Vaskob36053d2020-03-26 15:49:30 +0100937 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
938 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
939
940 return yin_parse_content(ctx, subelems, 2, LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +0200941}
942
David Sedlák5545f5d2019-07-11 11:55:16 +0200943/**
David Sedlákc1771b12019-07-10 15:55:46 +0200944 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +0200945 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +0200946 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200947 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200948 * @param[in] elem_type Type of element can be set to LY_STMT_ORGANIZATION or LY_STMT_CONTACT or LY_STMT_DESCRIPTION or LY_STMT_REFERENCE.
David Sedlákb4e44562019-07-04 15:42:12 +0200949 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200950 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200951 *
952 * @return LY_ERR values.
953 */
954static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100955yin_parse_meta(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200956{
Radek Krejcid6b76452019-09-03 17:03:03 +0200957 assert(elem_type == LY_STMT_ORGANIZATION || elem_type == LY_STMT_CONTACT || elem_type == LY_STMT_DESCRIPTION || elem_type == LY_STMT_REFERENCE);
David Sedlákb4e44562019-07-04 15:42:12 +0200958
David Sedlák968ac342019-07-11 15:17:59 +0200959 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200960 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
961 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +0200962 };
David Sedlákdf2a9732019-08-07 13:23:16 +0200963 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100964 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
965 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, elem_type));
David Sedlákb4e44562019-07-04 15:42:12 +0200966
David Sedlákdf2a9732019-08-07 13:23:16 +0200967 /* parse content */
Michal Vaskob36053d2020-03-26 15:49:30 +0100968 return yin_parse_content(ctx, subelems, 2, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200969}
970
971/**
David Sedlákc1771b12019-07-10 15:55:46 +0200972 * @brief Parse error-message element.
973 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200974 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +0200975 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200976 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +0200977 *
978 * @return LY_ERR values.
979 */
980static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100981yin_parse_err_msg(struct lys_yin_parser_ctx *ctx, const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +0200982{
David Sedlák968ac342019-07-11 15:17:59 +0200983 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200984 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
985 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +0200986 };
David Sedlákc1771b12019-07-10 15:55:46 +0200987
David Sedlákdf2a9732019-08-07 13:23:16 +0200988 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100989 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
990 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, LY_STMT_ERROR_MESSAGE));
David Sedlákdf2a9732019-08-07 13:23:16 +0200991
Michal Vaskob36053d2020-03-26 15:49:30 +0100992 return yin_parse_content(ctx, subelems, 2, LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +0200993}
994
995/**
David Sedlák6542aed2019-08-14 10:47:43 +0200996 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +0200997 *
998 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200999 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001000 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001001 *
1002 * @return LY_ERR values.
1003 */
1004static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001005yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001006{
David Sedlák6542aed2019-08-14 10:47:43 +02001007 struct lysp_type *type = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +02001008 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001009 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001010 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001011 type = *((struct lysp_type **)subinfo->dest);
1012 } else {
1013 type = (struct lysp_type *)subinfo->dest;
1014 }
1015 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001016 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001017 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001018 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001019 type->flags |= LYS_SET_TYPE;
1020 type = nested_type;
1021 }
David Sedlák374d2b32019-07-17 15:06:55 +02001022 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001023 {LY_STMT_BASE, type, 0},
1024 {LY_STMT_BIT, type, 0},
1025 {LY_STMT_ENUM, type, 0},
1026 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1027 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1028 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1029 {LY_STMT_PATTERN, type, 0},
1030 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1031 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1032 {LY_STMT_TYPE, type},
1033 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák374d2b32019-07-17 15:06:55 +02001034 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001035
1036 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1037 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1038 return yin_parse_content(ctx, subelems, 11, LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001039}
1040
David Sedlák1af868e2019-07-17 17:03:14 +02001041/**
1042 * @brief Parse max-elements element.
1043 *
1044 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001045 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001046 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001047 * @param[in,out] exts Extension instances to add to.
1048 *
1049 * @return LY_ERR values.
1050 */
1051static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001052yin_parse_maxelements(struct lys_yin_parser_ctx *ctx, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák1af868e2019-07-17 17:03:14 +02001053{
1054 const char *temp_val = NULL;
1055 char *ptr;
1056 unsigned long int num;
1057 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001058 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák1af868e2019-07-17 17:03:14 +02001059 };
David Sedlák374d2b32019-07-17 15:06:55 +02001060
David Sedlák1af868e2019-07-17 17:03:14 +02001061 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001062 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1063 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MAX_ELEMENTS));
David Sedlák1af868e2019-07-17 17:03:14 +02001064 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 +02001065 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001066 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001067 return LY_EVALID;
1068 }
1069
1070 if (strcmp(temp_val, "unbounded")) {
1071 errno = 0;
1072 num = strtoul(temp_val, &ptr, 10);
1073 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001074 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001075 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001076 return LY_EVALID;
1077 }
1078 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001079 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001080 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001081 return LY_EVALID;
1082 }
1083 *max = num;
1084 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001085 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1086 return yin_parse_content(ctx, subelems, 1, LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001087}
David Sedlák374d2b32019-07-17 15:06:55 +02001088
1089/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001090 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001091 *
1092 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001093 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001094 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001095 * @param[in,out] exts Extension instances to add to.
1096 *
1097 * @return LY_ERR values.
1098 */
1099static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001100yin_parse_minelements(struct lys_yin_parser_ctx *ctx, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák09e18c92019-07-18 11:17:11 +02001101{
1102 const char *temp_val = NULL;
1103 char *ptr;
1104 unsigned long int num;
1105 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001106 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák09e18c92019-07-18 11:17:11 +02001107 };
1108
1109 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001110 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1111 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MIN_ELEMENTS));
David Sedlák09e18c92019-07-18 11:17:11 +02001112
1113 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001114 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001115 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001116 return LY_EVALID;
1117 }
1118
1119 errno = 0;
1120 num = strtoul(temp_val, &ptr, 10);
1121 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001122 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001123 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001124 return LY_EVALID;
1125 }
1126 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001127 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001128 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001129 return LY_EVALID;
1130 }
1131 *min = num;
Michal Vaskob36053d2020-03-26 15:49:30 +01001132 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1133 return yin_parse_content(ctx, subelems, 1, LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001134}
1135
David Sedláka2dad212019-07-18 12:45:19 +02001136/**
1137 * @brief Parse min-elements or max-elements element.
1138 *
1139 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001140 * @param[in] parent Identification of parent element.
1141 * @param[in] current Identification of current element.
1142 * @param[in] dest Where the parsed value and flags should be stored.
1143 *
1144 * @return LY_ERR values.
1145 */
David Sedlák09e18c92019-07-18 11:17:11 +02001146static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001147yin_parse_minmax(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, enum ly_stmt current, void *dest)
David Sedlák09e18c92019-07-18 11:17:11 +02001148{
Radek Krejcid6b76452019-09-03 17:03:03 +02001149 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1150 assert(parent == LY_STMT_LEAF_LIST || parent == LY_STMT_REFINE || parent == LY_STMT_LIST || parent == LY_STMT_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001151 uint32_t *lim;
1152 uint16_t *flags;
1153 struct lysp_ext_instance **exts;
1154
Radek Krejcid6b76452019-09-03 17:03:03 +02001155 if (parent == LY_STMT_LEAF_LIST) {
1156 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001157 flags = &((struct lysp_node_leaflist *)dest)->flags;
1158 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001159 } else if (parent == LY_STMT_REFINE) {
1160 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001161 flags = &((struct lysp_refine *)dest)->flags;
1162 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001163 } else if (parent == LY_STMT_LIST) {
1164 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001165 flags = &((struct lysp_node_list *)dest)->flags;
1166 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001167 } else {
1168 lim = ((struct minmax_dev_meta *)dest)->lim;
1169 flags = ((struct minmax_dev_meta *)dest)->flags;
1170 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001171 }
1172
Radek Krejcid6b76452019-09-03 17:03:03 +02001173 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001174 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001175 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001176 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001177 }
1178
1179 return LY_SUCCESS;
1180}
1181
1182/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001183 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001184 *
1185 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001186 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001187 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001188 *
1189 * @return LY_ERR values.
1190 */
1191static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001192yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001193{
1194 const char *temp_val;
1195 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001196 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedláka2dad212019-07-18 12:45:19 +02001197 };
1198
Michal Vaskob36053d2020-03-26 15:49:30 +01001199 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1200 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_ORDERED_BY));
David Sedláka2dad212019-07-18 12:45:19 +02001201 if (strcmp(temp_val, "system") == 0) {
1202 *flags |= LYS_ORDBY_SYSTEM;
1203 } else if (strcmp(temp_val, "user") == 0) {
1204 *flags |= LYS_ORDBY_USER;
1205 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001206 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1207 "ordered-by", "system", "user");
Michal Vaskob36053d2020-03-26 15:49:30 +01001208 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001209 return LY_EVALID;
1210 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001211 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001212
Michal Vaskob36053d2020-03-26 15:49:30 +01001213 return yin_parse_content(ctx, subelems, 1, LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001214}
1215
1216/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001217 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001218 *
1219 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001220 * @param[in] any_kw Identification of current element, can be set to LY_STMT_ANYDATA or LY_STMT_ANYXML
David Sedlákad83cf92019-08-13 12:53:53 +02001221 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001222 *
1223 * @return LY_ERR values.
1224 */
1225static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001226yin_parse_any(struct lys_yin_parser_ctx *ctx, enum ly_stmt any_kw, struct tree_node_meta *node_meta)
David Sedlák8a83bbb2019-07-18 14:46:00 +02001227{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001228 struct lysp_node_anydata *any;
1229
David Sedlák8d552d62019-08-06 15:29:05 +02001230 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001231 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001232 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001233 any->parent = node_meta->parent;
1234
David Sedlákbf8a2b72019-08-14 16:48:10 +02001235 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001236 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1237 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &any->name, Y_IDENTIF_ARG, any_kw));
David Sedlák8a83bbb2019-07-18 14:46:00 +02001238
1239 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001240 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1241 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1242 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1243 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1244 {LY_STMT_MUST, &any->musts, 0},
1245 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1246 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1247 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1248 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8a83bbb2019-07-18 14:46:00 +02001249 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001250 return yin_parse_content(ctx, subelems, 9, any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001251}
1252
1253/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001254 * @brief parse leaf element.
1255 *
1256 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001257 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001258 *
1259 * @return LY_ERR values.
1260 */
1261static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001262yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001263{
David Sedlák203ca3a2019-07-18 15:26:25 +02001264 struct lysp_node_leaf *leaf;
1265
David Sedlák8d552d62019-08-06 15:29:05 +02001266 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001267 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001268 leaf->nodetype = LYS_LEAF;
1269 leaf->parent = node_meta->parent;
1270
David Sedlák203ca3a2019-07-18 15:26:25 +02001271 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001272 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1273 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, LY_STMT_LEAF));
David Sedlák203ca3a2019-07-18 15:26:25 +02001274
1275 /* parse content */
1276 struct yin_subelement subelems[12] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001277 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1278 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1279 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1280 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1281 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1282 {LY_STMT_MUST, &leaf->musts, 0},
1283 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1284 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1285 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1286 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1287 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1288 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001289 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001290 return yin_parse_content(ctx, subelems, 12, LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001291}
1292
1293/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001294 * @brief Parse leaf-list element.
1295 *
1296 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001297 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001298 *
1299 * @return LY_ERR values.
1300 */
1301static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001302yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001303{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001304 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001305
Michal Vaskob36053d2020-03-26 15:49:30 +01001306 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001307
David Sedlákc3da3ef2019-07-19 12:56:08 +02001308 llist->nodetype = LYS_LEAFLIST;
1309 llist->parent = node_meta->parent;
1310
David Sedlákc3da3ef2019-07-19 12:56:08 +02001311 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001312 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1313 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, LY_STMT_LEAF_LIST));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001314
1315 /* parse content */
1316 struct yin_subelement subelems[14] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001317 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1318 {LY_STMT_DEFAULT, &llist->dflts, 0},
1319 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1320 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1321 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1322 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1323 {LY_STMT_MUST, &llist->musts, 0},
1324 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1325 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1326 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1327 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1328 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1329 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1330 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001331 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001332 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001333
David Sedlákbf8a2b72019-08-14 16:48:10 +02001334 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001335 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001336 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001337 return LY_EVALID;
1338 }
1339 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001340 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001341 return LY_EVALID;
1342 }
1343
1344 return LY_SUCCESS;
1345}
1346
1347/**
David Sedlák04e17b22019-07-19 15:29:48 +02001348 * @brief Parse typedef element.
1349 *
1350 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001351 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001352 *
1353 * @return LY_ERR values.
1354 */
1355static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001356yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001357{
1358 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001359 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vaskob36053d2020-03-26 15:49:30 +01001360 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001361
1362 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001363 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1364 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, LY_STMT_TYPEDEF));
David Sedlák04e17b22019-07-19 15:29:48 +02001365
1366 /* parse content */
1367 struct yin_subelement subelems[7] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001368 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1369 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1370 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1371 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1372 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1373 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1374 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001375 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001376 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001377
1378 /* store data for collision check */
Michal Vasko1bf09392020-03-27 12:38:10 +01001379 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
David Sedláke8b74df2019-08-14 14:18:22 +02001380 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0) == -1, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001381 }
1382
1383 return LY_SUCCESS;
1384}
1385
1386/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001387 * @brief Parse refine element.
1388 *
1389 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001390 * @param[in,out] refines Refines to add to.
1391 *
1392 * @return LY_ERR values.
1393 */
1394static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001395yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001396{
1397 struct lysp_refine *rf;
1398
1399 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001400 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001401
1402 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001403 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1404 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1405 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001406
1407 /* parse content */
1408 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001409 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1410 {LY_STMT_DEFAULT, &rf->dflts, 0},
1411 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1412 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
1413 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1414 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1415 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1416 {LY_STMT_MUST, &rf->musts, 0},
1417 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1418 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1419 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001420 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001421 return yin_parse_content(ctx, subelems, 11, LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001422}
1423
1424/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001425 * @brief Parse uses element.
1426 *
1427 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001428 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001429 *
1430 * @return LY_ERR values.
1431 */
1432static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001433yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001434{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001435 struct lysp_node_uses *uses;
1436
David Sedlák8d552d62019-08-06 15:29:05 +02001437 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001438 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001439 uses->nodetype = LYS_USES;
1440 uses->parent = node_meta->parent;
1441
David Sedlák0d6de5a2019-07-22 13:25:44 +02001442 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001443 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1444 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, LY_STMT_USES));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001445
1446 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001447 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001448 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001449 {LY_STMT_AUGMENT, &augments, 0},
1450 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1451 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1452 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1453 {LY_STMT_REFINE, &uses->refines, 0},
1454 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1455 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1456 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001457 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001458 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001459 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1460
1461 return LY_SUCCESS;
1462}
1463
1464/**
David Sedlákaa854b02019-07-22 14:17:10 +02001465 * @brief Parse revision element.
1466 *
1467 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001468 * @param[in,out] revs Parsed revisions to add to.
1469 *
1470 * @return LY_ERR values.
1471 */
1472static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001473yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001474{
1475 struct lysp_revision *rev;
1476 const char *temp_date = NULL;
1477
1478 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001479 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001480
1481 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001482 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1483 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, &temp_date, Y_STR_ARG, LY_STMT_REVISION));
David Sedlákaa854b02019-07-22 14:17:10 +02001484 /* check value */
1485 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001486 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001487 return LY_EVALID;
1488 }
1489 strcpy(rev->date, temp_date);
Michal Vaskob36053d2020-03-26 15:49:30 +01001490 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001491
1492 /* parse content */
1493 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001494 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1495 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1496 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001497 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001498 return yin_parse_content(ctx, subelems, 3, LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001499}
1500
David Sedlák5e13dea2019-07-22 16:06:45 +02001501/**
1502 * @brief Parse include element.
1503 *
1504 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001505 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1506 *
1507 * @return LY_ERR values.
1508 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001509static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001510yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001511{
1512 struct lysp_include *inc;
1513
1514 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001515 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001516
1517 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001518 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1519 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, LY_STMT_INCLUDE));
David Sedlák0c2bab92019-07-22 15:33:19 +02001520
1521 /* submodules share the namespace with the module names, so there must not be
1522 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001523 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xmlctx->ctx, inc->name)) {
David Sedlák1538a842019-08-08 15:38:51 +02001524 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001525 return LY_EVALID;
1526 }
1527
1528 /* parse content */
1529 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001530 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1531 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1532 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1533 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák0c2bab92019-07-22 15:33:19 +02001534 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001535 return yin_parse_content(ctx, subelems, 4, LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001536}
1537
David Sedlákaa854b02019-07-22 14:17:10 +02001538/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001539 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001540 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001541 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001542 * @param[in,out] rev Array to store the parsed value in.
1543 * @param[in,out] exts Extension instances to add to.
1544 *
1545 * @return LY_ERR values.
1546 */
1547static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001548yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001549{
1550 const char *temp_rev;
1551 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001552 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001553 };
1554
Michal Vaskob36053d2020-03-26 15:49:30 +01001555 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1556 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, LY_STMT_REVISION_DATE));
David Sedlákdfbbb442019-08-06 16:33:21 +02001557 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
Michal Vaskob36053d2020-03-26 15:49:30 +01001558 FREE_STRING(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001559
1560 strcpy(rev, temp_rev);
Michal Vaskob36053d2020-03-26 15:49:30 +01001561 FREE_STRING(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001562
Michal Vaskob36053d2020-03-26 15:49:30 +01001563 return yin_parse_content(ctx, subelems, 1, LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001564}
1565
1566/**
1567 * @brief Parse config element.
1568 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001569 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001570 * @param[in,out] flags Flags to add to.
1571 * @param[in,out] exts Extension instances to add to.
1572 *
1573 * @return LY_ERR values.
1574 */
1575static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001576yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001577{
1578 const char *temp_val = NULL;
1579 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001580 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001581 };
1582
Michal Vaskob36053d2020-03-26 15:49:30 +01001583 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1584 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_CONFIG));
David Sedlákdfbbb442019-08-06 16:33:21 +02001585 if (strcmp(temp_val, "true") == 0) {
1586 *flags |= LYS_CONFIG_W;
1587 } else if (strcmp(temp_val, "false") == 0) {
1588 *flags |= LYS_CONFIG_R;
1589 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001590 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
1591 "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001592 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001593 return LY_EVALID;
1594 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001595 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001596
Michal Vaskob36053d2020-03-26 15:49:30 +01001597 return yin_parse_content(ctx, subelems, 1, LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001598}
1599
1600/**
1601 * @brief Parse yang-version element.
1602 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001603 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001604 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001605 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001606 *
1607 * @return LY_ERR values.
1608 */
1609static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001610yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001611{
1612 const char *temp_version = NULL;
1613 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001614 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001615 };
1616
Michal Vaskob36053d2020-03-26 15:49:30 +01001617 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1618 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, LY_STMT_YANG_VERSION));
David Sedlákdfbbb442019-08-06 16:33:21 +02001619 if (strcmp(temp_version, "1.0") == 0) {
1620 *version = LYS_VERSION_1_0;
1621 } else if (strcmp(temp_version, "1.1") == 0) {
1622 *version = LYS_VERSION_1_1;
1623 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001624 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
1625 "yang-version", "1.0", "1.1");
Michal Vaskob36053d2020-03-26 15:49:30 +01001626 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001627 return LY_EVALID;
1628 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001629 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001630 ctx->mod_version = *version;
1631
Michal Vaskob36053d2020-03-26 15:49:30 +01001632 return yin_parse_content(ctx, subelems, 1, LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001633}
1634
1635/**
1636 * @brief Parse import element.
1637 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001638 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001639 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1640 *
1641 * @return LY_ERR values.
1642 */
1643static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001644yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001645{
1646 struct lysp_import *imp;
1647 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001648 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001649
1650 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001651 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1652 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1653 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1654 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1655 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001656 };
1657
1658 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001659 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1660 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
1661 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001662 /* check prefix validity */
1663 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1664
1665 return LY_SUCCESS;
1666}
1667
1668/**
1669 * @brief Parse mandatory element.
1670 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001671 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001672 * @param[in,out] flags Flags to add to.
1673 * @param[in,out] exts Extension instances to add to.
1674 *
1675 * @return LY_ERR values.
1676 */
1677static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001678yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001679{
1680 const char *temp_val = NULL;
1681 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001682 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001683 };
1684
Michal Vaskob36053d2020-03-26 15:49:30 +01001685 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1686 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MANDATORY));
David Sedlákdfbbb442019-08-06 16:33:21 +02001687 if (strcmp(temp_val, "true") == 0) {
1688 *flags |= LYS_MAND_TRUE;
1689 } else if (strcmp(temp_val, "false") == 0) {
1690 *flags |= LYS_MAND_FALSE;
1691 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001692 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1693 "mandatory", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001694 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001695 return LY_EVALID;
1696 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001697 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001698
Michal Vaskob36053d2020-03-26 15:49:30 +01001699 return yin_parse_content(ctx, subelems, 1, LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001700}
1701
1702/**
1703 * @brief Parse status element.
1704 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001705 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001706 * @param[in,out] flags Flags to add to.
1707 * @param[in,out] exts Extension instances to add to.
1708 *
1709 * @return LY_ERR values.
1710 */
1711static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001712yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001713{
1714 const char *value = NULL;
1715 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001716 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001717 };
1718
Michal Vaskob36053d2020-03-26 15:49:30 +01001719 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1720 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &value, Y_STR_ARG, LY_STMT_STATUS));
David Sedlákdfbbb442019-08-06 16:33:21 +02001721 if (strcmp(value, "current") == 0) {
1722 *flags |= LYS_STATUS_CURR;
1723 } else if (strcmp(value, "deprecated") == 0) {
1724 *flags |= LYS_STATUS_DEPRC;
1725 } else if (strcmp(value, "obsolete") == 0) {
1726 *flags |= LYS_STATUS_OBSLT;
1727 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001728 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
1729 "status", "current", "deprecated", "obsolete");
Michal Vaskob36053d2020-03-26 15:49:30 +01001730 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001731 return LY_EVALID;
1732 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001733 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001734
Michal Vaskob36053d2020-03-26 15:49:30 +01001735 return yin_parse_content(ctx, subelems, 1, LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001736}
1737
1738/**
1739 * @brief Parse when element.
1740 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001741 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001742 * @param[out] when_p When pointer to parse to.
1743 */
1744static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001745yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001746{
1747 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001748 LY_ERR ret = LY_SUCCESS;
1749
David Sedlákdfbbb442019-08-06 16:33:21 +02001750 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001751 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
1752 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1753 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001754 LY_CHECK_ERR_RET(ret, free(when), ret);
1755
David Sedlákdfbbb442019-08-06 16:33:21 +02001756 *when_p = when;
1757 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001758 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1759 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1760 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001761 };
1762
Michal Vaskob36053d2020-03-26 15:49:30 +01001763 return yin_parse_content(ctx, subelems, 3, LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001764}
1765
1766/**
1767 * @brief Parse yin-elemenet element.
1768 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001769 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001770 * @param[in,out] data Data to read from, always moved to currently handled position.
1771 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001772 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001773 *
1774 * @return LY_ERR values.
1775 */
1776static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001777yin_parse_yin_element(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001778{
1779 const char *temp_val = NULL;
1780 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001781 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001782 };
1783
Michal Vaskob36053d2020-03-26 15:49:30 +01001784 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1785 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_YIN_ELEMENT));
David Sedlákdfbbb442019-08-06 16:33:21 +02001786 if (strcmp(temp_val, "true") == 0) {
1787 *flags |= LYS_YINELEM_TRUE;
1788 } else if (strcmp(temp_val, "false") == 0) {
1789 *flags |= LYS_YINELEM_FALSE;
1790 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001791 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1792 "yin-element", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001793 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001794 return LY_EVALID;
1795 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001796 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001797
Michal Vaskob36053d2020-03-26 15:49:30 +01001798 return yin_parse_content(ctx, subelems, 1, LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001799}
1800
1801/**
1802 * @brief Parse argument element.
1803 *
Michal Vaskob36053d2020-03-26 15:49:30 +01001804 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001805 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1806 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001807 *
1808 * @return LY_ERR values.
1809 */
1810static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001811yin_parse_argument(struct lys_yin_parser_ctx *ctx, struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001812{
1813 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001814 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1815 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001816 };
1817
Michal Vaskob36053d2020-03-26 15:49:30 +01001818 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1819 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, LY_STMT_ARGUMENT));
David Sedlákdfbbb442019-08-06 16:33:21 +02001820
Michal Vaskob36053d2020-03-26 15:49:30 +01001821 return yin_parse_content(ctx, subelems, 2, LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001822}
1823
1824/**
1825 * @brief Parse the extension statement.
1826 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001827 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001828 * @param[in,out] extensions Extensions to add to.
1829 *
1830 * @return LY_ERR values.
1831 */
1832static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001833yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02001834{
1835 struct lysp_ext *ex;
Michal Vaskob36053d2020-03-26 15:49:30 +01001836 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
1837 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1838 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &ex->name, Y_IDENTIF_ARG, LY_STMT_EXTENSION));
David Sedlákdfbbb442019-08-06 16:33:21 +02001839
1840 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1841 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001842 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1843 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1844 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1845 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1846 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001847 };
1848
Michal Vaskob36053d2020-03-26 15:49:30 +01001849 return yin_parse_content(ctx, subelems, 5, LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001850}
1851
1852/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001853 * @brief Parse feature element.
1854 *
1855 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001856 * @param[in,out] features Features to add to.
1857 *
1858 * @return LY_ERR values.
1859 */
1860static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001861yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02001862{
1863 struct lysp_feature *feat;
1864
1865 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01001866 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02001867
1868 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001869 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1870 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, LY_STMT_FEATURE));
David Sedlák5e13dea2019-07-22 16:06:45 +02001871
1872 /* parse content */
1873 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001874 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1875 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
1876 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1877 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1878 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák5e13dea2019-07-22 16:06:45 +02001879 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001880 return yin_parse_content(ctx, subelems, 5, LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02001881}
1882
1883/**
David Sedlák28794f22019-07-22 16:45:00 +02001884 * @brief Parse identity element.
1885 *
1886 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02001887 * @param[in,out] identities Identities to add to.
1888 *
1889 * @return LY_ERR values.
1890 */
1891static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001892yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02001893{
1894 struct lysp_ident *ident;
1895
1896 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01001897 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02001898
1899 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001900 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1901 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, LY_STMT_IDENTITY));
David Sedlák28794f22019-07-22 16:45:00 +02001902
1903 /* parse content */
1904 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001905 {LY_STMT_BASE, &ident->bases, 0},
1906 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
1907 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
1908 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
1909 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
1910 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák28794f22019-07-22 16:45:00 +02001911 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001912 return yin_parse_content(ctx, subelems, 6, LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02001913}
1914
1915/**
David Sedlákaf536aa2019-07-23 13:42:23 +02001916 * @brief Parse list element.
1917 *
1918 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001919 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02001920 *
1921 * @return LY_ERR values.
1922 */
1923static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001924yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02001925{
David Sedlákaf536aa2019-07-23 13:42:23 +02001926 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02001927 LY_ERR ret = LY_SUCCESS;
1928 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02001929
Michal Vaskob36053d2020-03-26 15:49:30 +01001930 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02001931 list->nodetype = LYS_LIST;
1932 list->parent = node_meta->parent;
1933
David Sedlákaf536aa2019-07-23 13:42:23 +02001934 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001935 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1936 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, LY_STMT_LIST));
David Sedlákaf536aa2019-07-23 13:42:23 +02001937
1938 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02001939 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02001940 LY_STMT_ACTION, &list->actions, 0,
1941 LY_STMT_ANYDATA, &list->child, 0,
1942 LY_STMT_ANYXML, &list->child, 0,
1943 LY_STMT_CHOICE, &list->child, 0,
1944 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
1945 LY_STMT_CONTAINER, &list->child, 0,
1946 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
1947 LY_STMT_GROUPING, &list->groupings, 0,
1948 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
1949 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
1950 LY_STMT_LEAF, &list->child, 0,
1951 LY_STMT_LEAF_LIST, &list->child, 0,
1952 LY_STMT_LIST, &list->child, 0,
1953 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
1954 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
1955 LY_STMT_MUST, &list->musts, 0,
1956 LY_STMT_NOTIFICATION, &list->notifs, 0,
1957 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
1958 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
1959 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
1960 LY_STMT_TYPEDEF, &list->typedefs, 0,
1961 LY_STMT_UNIQUE, &list->uniques, 0,
1962 LY_STMT_USES, &list->child, 0,
1963 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
1964 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02001965 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01001966 ret = yin_parse_content(ctx, subelems, 25, LY_STMT_LIST, NULL, &list->exts);
David Sedlák81497a32019-08-13 16:56:26 +02001967 subelems_deallocator(25, subelems);
1968 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02001969
1970 /* finalize parent pointers to the reallocated items */
1971 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
1972
1973 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001974 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02001975 return LY_EVALID;
1976 }
1977
1978 return LY_SUCCESS;
1979}
1980
1981/**
David Sedlák031b9e72019-07-23 15:19:37 +02001982 * @brief Parse notification element.
1983 *
1984 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001985 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02001986 *
1987 * @return LY_ERR values.
1988 */
1989static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001990yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02001991{
1992 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001993 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02001994 LY_ERR ret = LY_SUCCESS;
1995 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02001996
1997 /* allocate new notification */
Michal Vaskob36053d2020-03-26 15:49:30 +01001998 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02001999 notif->nodetype = LYS_NOTIF;
2000 notif->parent = notif_meta->parent;
2001
2002 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002003 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2004 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, LY_STMT_NOTIFICATION));
David Sedlák031b9e72019-07-23 15:19:37 +02002005
2006 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002007 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002008 LY_STMT_ANYDATA, &notif->data, 0,
2009 LY_STMT_ANYXML, &notif->data, 0,
2010 LY_STMT_CHOICE, &notif->data, 0,
2011 LY_STMT_CONTAINER, &notif->data, 0,
2012 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2013 LY_STMT_GROUPING, &notif->groupings, 0,
2014 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2015 LY_STMT_LEAF, &notif->data, 0,
2016 LY_STMT_LEAF_LIST, &notif->data, 0,
2017 LY_STMT_LIST, &notif->data, 0,
2018 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2019 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2020 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2021 LY_STMT_TYPEDEF, &notif->typedefs, 0,
2022 LY_STMT_USES, &notif->data, 0,
2023 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002024 ));
2025
Michal Vaskob36053d2020-03-26 15:49:30 +01002026 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_NOTIFICATION, NULL, &notif->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002027 subelems_deallocator(16, subelems);
2028 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002029
2030 /* finalize parent pointers to the reallocated items */
2031 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2032
2033 return LY_SUCCESS;
2034}
2035
2036/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002037 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002038 *
2039 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002040 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002041 *
2042 * @return LY_ERR values.
2043 */
2044static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002045yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002046{
2047 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002048 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002049 LY_ERR ret = LY_SUCCESS;
2050 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002051
2052 /* create new grouping */
Michal Vaskob36053d2020-03-26 15:49:30 +01002053 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002054 grp->nodetype = LYS_GROUPING;
2055 grp->parent = gr_meta->parent;
2056
2057 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002058 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2059 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, LY_STMT_GROUPING));
David Sedláke3ce9ef2019-07-23 16:34:30 +02002060
2061 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002062 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002063 LY_STMT_ACTION, &grp->actions, 0,
2064 LY_STMT_ANYDATA, &grp->data, 0,
2065 LY_STMT_ANYXML, &grp->data, 0,
2066 LY_STMT_CHOICE, &grp->data, 0,
2067 LY_STMT_CONTAINER, &grp->data, 0,
2068 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2069 LY_STMT_GROUPING, &grp->groupings, 0,
2070 LY_STMT_LEAF, &grp->data, 0,
2071 LY_STMT_LEAF_LIST, &grp->data, 0,
2072 LY_STMT_LIST, &grp->data, 0,
2073 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2074 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2075 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2076 LY_STMT_TYPEDEF, &grp->typedefs, 0,
2077 LY_STMT_USES, &grp->data, 0,
2078 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002079 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002080 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_GROUPING, NULL, &grp->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002081 subelems_deallocator(16, subelems);
2082 LY_CHECK_RET(ret);
2083
David Sedláke3ce9ef2019-07-23 16:34:30 +02002084 /* finalize parent pointers to the reallocated items */
2085 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2086
2087 return LY_SUCCESS;
2088}
2089
2090/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002091 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002092 *
2093 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002094 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002095 *
2096 * @return LY_ERR values.
2097 */
2098static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002099yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002100{
David Sedlákf111bcb2019-07-23 17:15:51 +02002101 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002102 LY_ERR ret = LY_SUCCESS;
2103 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002104
2105 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002106 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002107 cont->nodetype = LYS_CONTAINER;
2108 cont->parent = node_meta->parent;
2109
David Sedlákf111bcb2019-07-23 17:15:51 +02002110 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002111 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2112 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, LY_STMT_CONTAINER));
David Sedlákf111bcb2019-07-23 17:15:51 +02002113
2114 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002115 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002116 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2117 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2118 LY_STMT_ANYXML, &cont->child, 0,
2119 LY_STMT_CHOICE, &cont->child, 0,
2120 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2121 LY_STMT_CONTAINER, &cont->child, 0,
2122 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2123 LY_STMT_GROUPING, &cont->groupings, 0,
2124 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2125 LY_STMT_LEAF, &cont->child, 0,
2126 LY_STMT_LEAF_LIST, &cont->child, 0,
2127 LY_STMT_LIST, &cont->child, 0,
2128 LY_STMT_MUST, &cont->musts, 0,
2129 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2130 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2131 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2132 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2133 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2134 LY_STMT_USES, &cont->child, 0,
2135 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2136 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002137 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002138 ret = yin_parse_content(ctx, subelems, 21, LY_STMT_CONTAINER, NULL, &cont->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002139 subelems_deallocator(21, subelems);
2140 LY_CHECK_RET(ret);
2141
David Sedlákf111bcb2019-07-23 17:15:51 +02002142 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2143
2144 return LY_SUCCESS;
2145}
2146
2147/**
David Sedlák5379d392019-07-24 10:42:03 +02002148 * @brief Parse case element.
2149 *
2150 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002151 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002152 *
2153 * @return LY_ERR values.
2154 */
2155static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002156yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002157{
David Sedlák5379d392019-07-24 10:42:03 +02002158 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002159 LY_ERR ret = LY_SUCCESS;
2160 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002161
2162 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002163 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002164 cas->nodetype = LYS_CASE;
2165 cas->parent = node_meta->parent;
2166
David Sedlák5379d392019-07-24 10:42:03 +02002167 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002168 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2169 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, LY_STMT_CASE));
David Sedlák5379d392019-07-24 10:42:03 +02002170
2171 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002172 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002173 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2174 LY_STMT_ANYXML, &cas->child, 0,
2175 LY_STMT_CHOICE, &cas->child, 0,
2176 LY_STMT_CONTAINER, &cas->child, 0,
2177 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2178 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2179 LY_STMT_LEAF, &cas->child, 0,
2180 LY_STMT_LEAF_LIST, &cas->child, 0,
2181 LY_STMT_LIST, &cas->child, 0,
2182 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2183 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2184 LY_STMT_USES, &cas->child, 0,
2185 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2186 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002187 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002188 ret = yin_parse_content(ctx, subelems, 14, LY_STMT_CASE, NULL, &cas->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002189 subelems_deallocator(14, subelems);
2190
2191 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002192}
2193
2194/**
David Sedlák05404f62019-07-24 14:11:53 +02002195 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002196 *
2197 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002198 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002199 *
2200 * @return LY_ERR values.
2201 */
2202LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002203yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002204{
David Sedlák81497a32019-08-13 16:56:26 +02002205 LY_ERR ret = LY_SUCCESS;
2206 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002207 struct lysp_node_choice *choice;
2208
2209 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002210 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002211
David Sedlákb7abcfa2019-07-24 12:33:35 +02002212 choice->nodetype = LYS_CHOICE;
2213 choice->parent = node_meta->parent;
2214
David Sedlákb7abcfa2019-07-24 12:33:35 +02002215 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002216 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2217 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, LY_STMT_CHOICE));
David Sedlákb7abcfa2019-07-24 12:33:35 +02002218
2219 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002220 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002221 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2222 LY_STMT_ANYXML, &choice->child, 0,
2223 LY_STMT_CASE, &choice->child, 0,
2224 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2225 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2226 LY_STMT_CONTAINER, &choice->child, 0,
2227 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2228 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2229 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2230 LY_STMT_LEAF, &choice->child, 0,
2231 LY_STMT_LEAF_LIST, &choice->child, 0,
2232 LY_STMT_LIST, &choice->child, 0,
2233 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2234 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2235 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2236 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2237 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002238 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002239 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_CHOICE, NULL, &choice->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002240 subelems_deallocator(17, subelems);
2241 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002242}
2243
2244/**
David Sedlák05404f62019-07-24 14:11:53 +02002245 * @brief Parse input or output element.
2246 *
2247 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002248 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002249 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2250 *
2251 * @return LY_ERR values.
2252 */
2253static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002254yin_parse_inout(struct lys_yin_parser_ctx *ctx, enum ly_stmt inout_kw, struct inout_meta *inout_meta)
David Sedlák05404f62019-07-24 14:11:53 +02002255{
David Sedlák81497a32019-08-13 16:56:26 +02002256 LY_ERR ret = LY_SUCCESS;
2257 struct yin_subelement *subelems = NULL;
2258
David Sedlák05404f62019-07-24 14:11:53 +02002259 /* initiate structure */
Radek Krejcid6b76452019-09-03 17:03:03 +02002260 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002261 inout_meta->inout_p->parent = inout_meta->parent;
2262
2263 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002264 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2265 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
David Sedlák05404f62019-07-24 14:11:53 +02002266
2267 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002268 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002269 LY_STMT_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2270 LY_STMT_ANYXML, &inout_meta->inout_p->data, 0,
2271 LY_STMT_CHOICE, &inout_meta->inout_p->data, 0,
2272 LY_STMT_CONTAINER, &inout_meta->inout_p->data, 0,
2273 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2274 LY_STMT_LEAF, &inout_meta->inout_p->data, 0,
2275 LY_STMT_LEAF_LIST, &inout_meta->inout_p->data, 0,
2276 LY_STMT_LIST, &inout_meta->inout_p->data, 0,
2277 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2278 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2279 LY_STMT_USES, &inout_meta->inout_p->data, 0,
2280 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002281 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002282 ret = yin_parse_content(ctx, subelems, 12, inout_kw, NULL, &inout_meta->inout_p->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002283 subelems_deallocator(12, subelems);
2284 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002285
Michal Vaskob83af8a2020-01-06 09:49:22 +01002286 if (!inout_meta->inout_p->data) {
2287 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2288 return LY_EVALID;
2289 }
2290
David Sedlák05404f62019-07-24 14:11:53 +02002291 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002292 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 +02002293
2294 return LY_SUCCESS;
2295}
2296
David Sedlák992fb7c2019-07-24 16:51:01 +02002297/**
2298 * @brief Parse action element.
2299 *
2300 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002301 * @param[in] act_meta Meta information about parent node and actions to add to.
2302 *
2303 * @return LY_ERR values.
2304 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002305static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002306yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002307{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002308 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002309 LY_ERR ret = LY_SUCCESS;
2310 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002311
2312 /* create new action */
Michal Vaskob36053d2020-03-26 15:49:30 +01002313 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *acts, act, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002314 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002315 act->parent = act_meta->parent;
2316
2317 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002318 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2319 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, LY_STMT_ACTION));
David Sedlák85d0eca2019-07-24 15:15:21 +02002320
2321 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002322 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002323 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2324 LY_STMT_GROUPING, &act->groupings, 0,
2325 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2326 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2327 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2328 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2329 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2330 LY_STMT_TYPEDEF, &act->typedefs, 0,
2331 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002332 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002333 ret = (yin_parse_content(ctx, subelems, 9, LY_STMT_ACTION, NULL, &act->exts));
David Sedlák81497a32019-08-13 16:56:26 +02002334 subelems_deallocator(9, subelems);
2335 LY_CHECK_RET(ret);
2336
David Sedlák85d0eca2019-07-24 15:15:21 +02002337 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2338
2339 return LY_SUCCESS;
2340}
2341
David Sedlák05404f62019-07-24 14:11:53 +02002342/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002343 * @brief Parse augment element.
2344 *
2345 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002346 * @param[in] aug_meta Meta information about parent node and augments to add to.
2347 *
2348 * @return LY_ERR values.
2349 */
2350static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002351yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002352{
2353 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002354 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002355 LY_ERR ret = LY_SUCCESS;
2356 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002357
2358 /* create new augment */
Michal Vaskob36053d2020-03-26 15:49:30 +01002359 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002360 aug->nodetype = LYS_AUGMENT;
2361 aug->parent = aug_meta->parent;
2362
2363 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002364 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2365 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2366 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002367
2368 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002369 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002370 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2371 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2372 LY_STMT_ANYXML, &aug->child, 0,
2373 LY_STMT_CASE, &aug->child, 0,
2374 LY_STMT_CHOICE, &aug->child, 0,
2375 LY_STMT_CONTAINER, &aug->child, 0,
2376 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2377 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
2378 LY_STMT_LEAF, &aug->child, 0,
2379 LY_STMT_LEAF_LIST, &aug->child, 0,
2380 LY_STMT_LIST, &aug->child, 0,
2381 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2382 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2383 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2384 LY_STMT_USES, &aug->child, 0,
2385 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2386 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002387 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002388 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_AUGMENT, NULL, &aug->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002389 subelems_deallocator(17, subelems);
2390 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002391
2392 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2393
2394 return LY_SUCCESS;
2395}
2396
David Sedlák8b754462019-07-25 16:22:13 +02002397/**
2398 * @brief Parse deviate element.
2399 *
2400 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002401 * @param[in] deviates Deviates to add to.
2402 *
2403 * @return LY_ERR values.
2404 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002405static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002406yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002407{
2408 LY_ERR ret = LY_SUCCESS;
2409 uint8_t dev_mod;
2410 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002411 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002412 struct lysp_deviate_add *d_add = NULL;
2413 struct lysp_deviate_rpl *d_rpl = NULL;
2414 struct lysp_deviate_del *d_del = NULL;
2415
2416 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002417 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2418 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_DEVIATE));
David Sedlák4ffcec82019-07-25 15:10:21 +02002419
2420 if (strcmp(temp_val, "not-supported") == 0) {
2421 dev_mod = LYS_DEV_NOT_SUPPORTED;
2422 } else if (strcmp(temp_val, "add") == 0) {
2423 dev_mod = LYS_DEV_ADD;
2424 } else if (strcmp(temp_val, "replace") == 0) {
2425 dev_mod = LYS_DEV_REPLACE;
2426 } else if (strcmp(temp_val, "delete") == 0) {
2427 dev_mod = LYS_DEV_DELETE;
2428 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002429 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
2430 "not-supported", "add", "replace", "delete");
Michal Vaskob36053d2020-03-26 15:49:30 +01002431 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002432 return LY_EVALID;
2433 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002434 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002435
2436 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2437 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002438 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002439 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002440 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák4ffcec82019-07-25 15:10:21 +02002441 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002442 ret = yin_parse_content(ctx, subelems, 1, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002443
2444 } else if (dev_mod == LYS_DEV_ADD) {
2445 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002446 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002447 d = (struct lysp_deviate *)d_add;
2448 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2449 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2450 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002451 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2452 {LY_STMT_DEFAULT, &d_add->dflts, 0},
2453 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2454 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2455 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2456 {LY_STMT_MUST, &d_add->musts, 0},
2457 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2458 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2459 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002460 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002461 ret = yin_parse_content(ctx, subelems, 9, LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002462
2463 } else if (dev_mod == LYS_DEV_REPLACE) {
2464 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002465 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002466 d = (struct lysp_deviate *)d_rpl;
2467 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2468 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2469 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002470 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2471 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2472 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2473 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2474 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2475 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2476 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2477 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002478 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002479 ret = yin_parse_content(ctx, subelems, 8, LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002480
2481 } else {
2482 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002483 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002484 d = (struct lysp_deviate *)d_del;
2485 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002486 {LY_STMT_DEFAULT, &d_del->dflts, 0},
2487 {LY_STMT_MUST, &d_del->musts, 0},
2488 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2489 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2490 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002491 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002492 ret = yin_parse_content(ctx, subelems, 5, LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002493 }
2494 LY_CHECK_GOTO(ret, cleanup);
2495
2496 d->mod = dev_mod;
2497 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002498 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002499
2500 return ret;
2501
2502cleanup:
2503 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002504 return ret;
2505}
2506
David Sedlák992fb7c2019-07-24 16:51:01 +02002507/**
David Sedlák8b754462019-07-25 16:22:13 +02002508 * @brief Parse deviation element.
2509 *
2510 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002511 * @param[in] deviations Deviations to add to.
2512 *
2513 * @return LY_ERR values.
2514 */
2515static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002516yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002517{
2518 struct lysp_deviation *dev;
2519
2520 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002521 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002522
2523 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002524 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2525 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2526 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
David Sedlák8b754462019-07-25 16:22:13 +02002527 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002528 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2529 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2530 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2531 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8b754462019-07-25 16:22:13 +02002532 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002533 return yin_parse_content(ctx, subelems, 4, LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002534}
2535
2536/**
David Sedlákb4e44562019-07-04 15:42:12 +02002537 * @brief Map keyword type to substatement info.
2538 *
2539 * @param[in] kw Keyword type.
2540 *
2541 * @return correct LYEXT_SUBSTMT information.
2542 */
2543static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002544kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002545{
2546 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002547 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002548 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002549 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002550 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002551 case LY_STMT_BELONGS_TO:
David Sedlákb4e44562019-07-04 15:42:12 +02002552 return LYEXT_SUBSTMT_BELONGSTO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002553 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002554 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002555 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002556 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002557 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002558 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002559 case LY_STMT_ERROR_APP_TAG:
David Sedlákb4e44562019-07-04 15:42:12 +02002560 return LYEXT_SUBSTMT_ERRTAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002561 case LY_STMT_ERROR_MESSAGE:
David Sedlákb4e44562019-07-04 15:42:12 +02002562 return LYEXT_SUBSTMT_ERRMSG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002563 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002564 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002565 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002566 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002567 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002568 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002569 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002570 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002571 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002572 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002573 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002574 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002575 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002576 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002577 case LY_STMT_REVISION_DATE:
David Sedlákb4e44562019-07-04 15:42:12 +02002578 return LYEXT_SUBSTMT_REVISIONDATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002579 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002580 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002581 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002582 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002583 case LY_STMT_YANG_VERSION:
David Sedlákb4e44562019-07-04 15:42:12 +02002584 return LYEXT_SUBSTMT_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002585 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002586 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002587 case LY_STMT_REQUIRE_INSTANCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002588 return LYEXT_SUBSTMT_REQINSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002589 case LY_STMT_YIN_ELEMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002590 return LYEXT_SUBSTMT_YINELEM;
Radek Krejcid6b76452019-09-03 17:03:03 +02002591 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002592 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002593 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002594 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002595 case LY_STMT_ORDERED_BY:
David Sedlákb4e44562019-07-04 15:42:12 +02002596 return LYEXT_SUBSTMT_ORDEREDBY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002597 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002598 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002599 case LY_STMT_FRACTION_DIGITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002600 return LYEXT_SUBSTMT_FRACDIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002601 case LY_STMT_MAX_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002602 return LYEXT_SUBSTMT_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002603 case LY_STMT_MIN_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002604 return LYEXT_SUBSTMT_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02002605 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002606 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002607 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002608 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002609 case LY_STMT_IF_FEATURE:
David Sedlákb4e44562019-07-04 15:42:12 +02002610 return LYEXT_SUBSTMT_IFFEATURE;
2611 default:
2612 return LYEXT_SUBSTMT_SELF;
2613 }
2614}
2615
David Sedlákc5b20842019-08-13 10:18:31 +02002616/**
2617 * @brief map keyword to keyword-group.
2618 *
2619 * @param[in] ctx YIN parser context used for logging.
2620 * @param[in] kw Keyword that is child of module or submodule.
2621 * @param[out] group Group of keyword.
2622 *
2623 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2624 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002625static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002626kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002627{
2628 switch (kw) {
2629 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02002630 case LY_STMT_NONE:
2631 case LY_STMT_NAMESPACE:
2632 case LY_STMT_PREFIX:
2633 case LY_STMT_BELONGS_TO:
2634 case LY_STMT_YANG_VERSION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002635 *group = Y_MOD_MODULE_HEADER;
2636 break;
2637 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02002638 case LY_STMT_INCLUDE:
2639 case LY_STMT_IMPORT:
David Sedláke6cd89e2019-08-07 12:46:02 +02002640 *group = Y_MOD_LINKAGE;
2641 break;
2642 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02002643 case LY_STMT_ORGANIZATION:
2644 case LY_STMT_CONTACT:
2645 case LY_STMT_DESCRIPTION:
2646 case LY_STMT_REFERENCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002647 *group = Y_MOD_META;
2648 break;
2649 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02002650 case LY_STMT_REVISION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002651 *group = Y_MOD_REVISION;
2652 break;
2653 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02002654 case LY_STMT_ANYDATA:
2655 case LY_STMT_ANYXML:
2656 case LY_STMT_AUGMENT:
2657 case LY_STMT_CHOICE:
2658 case LY_STMT_CONTAINER:
2659 case LY_STMT_DEVIATION:
2660 case LY_STMT_EXTENSION:
2661 case LY_STMT_FEATURE:
2662 case LY_STMT_GROUPING:
2663 case LY_STMT_IDENTITY:
2664 case LY_STMT_LEAF:
2665 case LY_STMT_LEAF_LIST:
2666 case LY_STMT_LIST:
2667 case LY_STMT_NOTIFICATION:
2668 case LY_STMT_RPC:
2669 case LY_STMT_TYPEDEF:
2670 case LY_STMT_USES:
2671 case LY_STMT_EXTENSION_INSTANCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002672 *group = Y_MOD_BODY;
2673 break;
2674 default:
Michal Vaskob36053d2020-03-26 15:49:30 +01002675 LOGINT(ctx->xmlctx->ctx);
David Sedláke6cd89e2019-08-07 12:46:02 +02002676 return LY_EINT;
2677 }
2678
2679 return LY_SUCCESS;
2680}
2681
David Sedlákc5b20842019-08-13 10:18:31 +02002682/**
2683 * @brief Check if relative order of two keywords is valid.
2684 *
2685 * @param[in] ctx YIN parser context used for logging.
2686 * @param[in] kw Current keyword.
2687 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002688 * @param[in] parrent Identification of parrent element, can be se to to LY_STMT_MODULE of LY_STMT_SUBMODULE,
David Sedlákc5b20842019-08-13 10:18:31 +02002689 * because relative order is required only in module and submodule sub-elements, used for logging.
2690 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002691 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002692 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002693static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002694yin_check_relative_order(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum ly_stmt next_kw, enum ly_stmt parrent)
David Sedláke6cd89e2019-08-07 12:46:02 +02002695{
Radek Krejcid6b76452019-09-03 17:03:03 +02002696 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002697 enum yang_module_stmt gr, next_gr;
2698
2699 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2700 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2701
2702 if (gr > next_gr) {
2703 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2704 return LY_EVALID;
2705 }
2706
2707 return LY_SUCCESS;
2708}
2709
David Sedlákc5dd0942019-09-13 10:23:59 +02002710/**
2711 * @brief Get element name prefixed by full URI of xml namespace.
2712 *
2713 * @param[in] ctx YIN parser context used for logging and to get inormation about xml namespaces.
2714 * @param[in] name Name of element.
2715 * @param[in] name_len Length of element name.
2716 * @param[in] prefix Prefix of element.
2717 * @param[in] prefix_len Length of element prefix.
2718 *
2719 * @return Element name prefixed by URI on success, NULL on failure.
2720 */
2721static const char *
Michal Vaskob36053d2020-03-26 15:49:30 +01002722name2nsname(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len)
David Sedlák068dd352019-09-13 09:08:22 +02002723{
Michal Vaskob36053d2020-03-26 15:49:30 +01002724 const struct lyxml_ns *ns = lyxml_ns_get(ctx->xmlctx, prefix, prefix_len);
2725 LY_CHECK_ERR_RET(!ns, LOGINT(ctx->xmlctx->ctx), NULL);
David Sedlák068dd352019-09-13 09:08:22 +02002726
Radek Krejci02728562019-09-18 14:13:05 +02002727 if (!strcmp(ns->uri, YIN_NS_URI)) {
2728 /* standard YANG statement in YIN namespace - keep it unprefixed as in case of YANG */
Michal Vaskob36053d2020-03-26 15:49:30 +01002729 return lydict_insert(ctx->xmlctx->ctx, name, name_len);
Radek Krejci02728562019-09-18 14:13:05 +02002730 }
2731 /* some statement in special namespace (extension instance) */
David Sedláke0ef1c62019-09-13 10:05:55 +02002732 size_t ns_len = strlen(ns->uri);
2733 size_t len = ns_len + name_len + 1; /* +1 because of ':' delimiter between ns and actual name */
2734
2735 char *result;
2736 char *temp;
2737 temp = result = malloc(sizeof(*temp) * (len + 1)); /* +1 for '\0' terminator */
Michal Vaskob36053d2020-03-26 15:49:30 +01002738 LY_CHECK_ERR_RET(!temp, LOGMEM(ctx->xmlctx->ctx), NULL);
David Sedláke0ef1c62019-09-13 10:05:55 +02002739
2740 strcpy(result, ns->uri);
2741 result[ns_len] = ':';
2742 temp = &result[ns_len + 1];
2743 strncpy(temp, name, name_len);
2744 result[len] = '\0';
2745
Michal Vaskob36053d2020-03-26 15:49:30 +01002746 return lydict_insert_zc(ctx->xmlctx->ctx, result);
David Sedlák068dd352019-09-13 09:08:22 +02002747}
2748
David Sedlákd6e56892019-07-01 15:40:24 +02002749LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002750yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
2751 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02002752{
2753 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01002754 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02002755 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002756 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002757
Michal Vaskob36053d2020-03-26 15:49:30 +01002758 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02002759
Michal Vaskob36053d2020-03-26 15:49:30 +01002760 if (ctx->xmlctx->ws_only) {
2761 /* check whether there are any children */
2762 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
2763 } else {
2764 /* we want to parse the value */
2765 next_status = LYXML_ELEM_CLOSE;
2766 }
2767
2768 if (next_status == LYXML_ELEMENT) {
2769 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
2770
2771 /* current element has subelements as content */
2772 while (ctx->xmlctx->status == LYXML_ELEMENT) {
2773 /* match keyword */
2774 last_kw = kw;
2775 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
2776 ctx->xmlctx->prefix_len, current_element);
2777
2778 /* check if this element can be child of current element */
2779 subelem = get_record(kw, subelem_info_size, subelem_info);
2780 if (!subelem) {
2781 if (current_element == LY_STMT_DEVIATE && isdevsub(kw)) {
2782 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2783 } else {
2784 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
2785 ctx->xmlctx->name, ly_stmt2str(current_element));
2786 }
2787 ret = LY_EVALID;
2788 goto cleanup;
2789 }
2790
2791 /* relative order is required only in module and submodule sub-elements */
2792 if (current_element == LY_STMT_MODULE || current_element == LY_STMT_SUBMODULE) {
2793 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2794 LY_CHECK_GOTO(ret, cleanup);
2795 }
2796
2797 /* flag check */
2798 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
2799 /* subelement uniquenes */
2800 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
2801 return LY_EVALID;
2802 }
2803 if (subelem->flags & YIN_SUBELEM_FIRST) {
2804 /* subelement is supposed to be defined as first subelement */
2805 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
2806 LY_CHECK_GOTO(ret, cleanup);
2807 }
2808 if (subelem->flags & YIN_SUBELEM_VER2) {
2809 /* subelement is supported only in version 1.1 or higher */
2810 if (ctx->mod_version < 2) {
2811 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02002812 ret = LY_EVALID;
2813 goto cleanup;
2814 }
David Sedlákd6e56892019-07-01 15:40:24 +02002815 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002816 /* note that element was parsed for easy uniqueness check in next iterations */
2817 subelem->flags |= YIN_SUBELEM_PARSED;
2818
2819 switch (kw) {
2820 /* call responsible function */
2821 case LY_STMT_EXTENSION_INSTANCE:
2822 ret = yin_parse_extension_instance(ctx, kw2lyext_substmt(current_element),
2823 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
2824 break;
2825 case LY_STMT_ACTION:
2826 case LY_STMT_RPC:
2827 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
2828 break;
2829 case LY_STMT_ANYDATA:
2830 case LY_STMT_ANYXML:
2831 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
2832 break;
2833 case LY_STMT_ARGUMENT:
2834 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
2835 break;
2836 case LY_STMT_AUGMENT:
2837 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
2838 break;
2839 case LY_STMT_BASE:
2840 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
2841 break;
2842 case LY_STMT_BELONGS_TO:
2843 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
2844 break;
2845 case LY_STMT_BIT:
2846 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
2847 break;
2848 case LY_STMT_CASE:
2849 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
2850 break;
2851 case LY_STMT_CHOICE:
2852 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
2853 break;
2854 case LY_STMT_CONFIG:
2855 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
2856 break;
2857 case LY_STMT_CONTACT:
2858 case LY_STMT_DESCRIPTION:
2859 case LY_STMT_ORGANIZATION:
2860 case LY_STMT_REFERENCE:
2861 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
2862 break;
2863 case LY_STMT_CONTAINER:
2864 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
2865 break;
2866 case LY_STMT_DEFAULT:
2867 case LY_STMT_ERROR_APP_TAG:
2868 case LY_STMT_KEY:
2869 case LY_STMT_PRESENCE:
2870 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
2871 break;
2872 case LY_STMT_DEVIATE:
2873 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
2874 break;
2875 case LY_STMT_DEVIATION:
2876 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
2877 break;
2878 case LY_STMT_ENUM:
2879 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
2880 break;
2881 case LY_STMT_ERROR_MESSAGE:
2882 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
2883 break;
2884 case LY_STMT_EXTENSION:
2885 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
2886 break;
2887 case LY_STMT_FEATURE:
2888 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
2889 break;
2890 case LY_STMT_FRACTION_DIGITS:
2891 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
2892 break;
2893 case LY_STMT_GROUPING:
2894 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
2895 break;
2896 case LY_STMT_IDENTITY:
2897 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
2898 break;
2899 case LY_STMT_IF_FEATURE:
2900 case LY_STMT_UNITS:
2901 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
2902 break;
2903 case LY_STMT_IMPORT:
2904 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
2905 break;
2906 case LY_STMT_INCLUDE:
2907 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
2908 break;
2909 case LY_STMT_INPUT:
2910 case LY_STMT_OUTPUT:
2911 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
2912 break;
2913 case LY_STMT_LEAF:
2914 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
2915 break;
2916 case LY_STMT_LEAF_LIST:
2917 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
2918 break;
2919 case LY_STMT_LENGTH:
2920 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
2921 break;
2922 case LY_STMT_LIST:
2923 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
2924 break;
2925 case LY_STMT_MANDATORY:
2926 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
2927 break;
2928 case LY_STMT_MAX_ELEMENTS:
2929 case LY_STMT_MIN_ELEMENTS:
2930 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
2931 break;
2932 case LY_STMT_MODIFIER:
2933 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
2934 break;
2935 case LY_STMT_MUST:
2936 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
2937 break;
2938 case LY_STMT_NAMESPACE:
2939 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
2940 break;
2941 case LY_STMT_NOTIFICATION:
2942 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
2943 break;
2944 case LY_STMT_ORDERED_BY:
2945 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
2946 break;
2947 case LY_STMT_PATH:
2948 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
2949 break;
2950 case LY_STMT_PATTERN:
2951 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
2952 break;
2953 case LY_STMT_VALUE:
2954 case LY_STMT_POSITION:
2955 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
2956 break;
2957 case LY_STMT_PREFIX:
2958 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
2959 break;
2960 case LY_STMT_RANGE:
2961 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
2962 break;
2963 case LY_STMT_REFINE:
2964 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
2965 break;
2966 case LY_STMT_REQUIRE_INSTANCE:
2967 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
2968 break;
2969 case LY_STMT_REVISION:
2970 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
2971 break;
2972 case LY_STMT_REVISION_DATE:
2973 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
2974 break;
2975 case LY_STMT_STATUS:
2976 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
2977 break;
2978 case LY_STMT_TYPE:
2979 ret = yin_parse_type(ctx, current_element, subelem);
2980 break;
2981 case LY_STMT_TYPEDEF:
2982 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
2983 break;
2984 case LY_STMT_UNIQUE:
2985 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
2986 break;
2987 case LY_STMT_USES:
2988 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
2989 break;
2990 case LY_STMT_WHEN:
2991 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
2992 break;
2993 case LY_STMT_YANG_VERSION:
2994 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
2995 break;
2996 case LY_STMT_YIN_ELEMENT:
2997 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
2998 break;
2999 case LY_STMT_ARG_TEXT:
3000 case LY_STMT_ARG_VALUE:
3001 /* TODO what to do with content/attributes? */
3002 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3003 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3004 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3005 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3006 }
3007 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3008 break;
3009 default:
3010 LOGINT(ctx->xmlctx->ctx);
3011 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003012 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003013 LY_CHECK_GOTO(ret, cleanup);
3014 subelem = NULL;
3015
3016 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003017 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003018 } else {
3019 LY_CHECK_RET(ret);
3020 /* elements with text or none content */
3021 /* save text content, if text_content isn't set, it's just ignored */
3022 /* no resources are allocated in this branch, no need to use cleanup label */
3023 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3024 if (text_content) {
3025 *text_content = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3026 LY_CHECK_RET(!*text_content, LY_EMEM);
3027 }
3028
3029 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003030 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003031
David Sedlák8b754462019-07-25 16:22:13 +02003032 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3033 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003034
3035cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003036 return ret;
3037}
3038
David Sedlák619db942019-07-03 14:47:30 +02003039LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003040yin_parse_extension_instance(struct lys_yin_parser_ctx *ctx, LYEXT_SUBSTMT subelem, uint32_t subelem_index,
3041 struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003042{
David Sedlák1e2cdd02019-06-27 14:17:43 +02003043 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003044 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003045
Michal Vaskob36053d2020-03-26 15:49:30 +01003046 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3047
3048 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003049
3050 e->yin = 0;
3051 /* store name and insubstmt info */
Michal Vaskob36053d2020-03-26 15:49:30 +01003052 e->name = name2nsname(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len);
David Sedláke0ef1c62019-09-13 10:05:55 +02003053 LY_CHECK_RET(!e->name, LY_EMEM);
David Sedlák619db942019-07-03 14:47:30 +02003054 e->insubstmt = subelem;
3055 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003056 e->yin |= LYS_YIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01003057 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003058
David Sedlákb1a78352019-06-28 16:16:29 +02003059 /* store attributes as subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003060 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3061 if (!ctx->xmlctx->prefix) {
David Sedlákb1a78352019-06-28 16:16:29 +02003062 new_subelem = calloc(1, sizeof(*new_subelem));
3063 if (!e->child) {
3064 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003065 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003066 last_subelem->next = new_subelem;
3067 }
3068 last_subelem = new_subelem;
3069
3070 last_subelem->flags |= LYS_YIN_ATTR;
Michal Vaskob36053d2020-03-26 15:49:30 +01003071 last_subelem->stmt = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák169cc522019-08-15 13:23:45 +02003072 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003073 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák169cc522019-08-15 13:23:45 +02003074
Michal Vaskob36053d2020-03-26 15:49:30 +01003075 last_subelem->arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
David Sedlák169cc522019-08-15 13:23:45 +02003076 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003077 } else {
3078 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003079 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003080
3081 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003082 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003083
David Sedlákf250ecf2019-07-01 11:02:05 +02003084 /* parse subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003085 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3086 if (ctx->xmlctx->ws_only) {
3087 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3088 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3089 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3090 if (!e->child) {
3091 e->child = new_subelem;
3092 } else {
3093 last_subelem->next = new_subelem;
David Sedlákb1a78352019-06-28 16:16:29 +02003094 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003095 last_subelem = new_subelem;
David Sedlák169cc522019-08-15 13:23:45 +02003096
Michal Vaskob36053d2020-03-26 15:49:30 +01003097 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3098 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003099 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003100 } else if (ctx->xmlctx->value_len) {
3101 /* save text content */
3102 e->argument = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3103 LY_CHECK_RET(!e->argument, LY_EMEM);
3104
3105 /* parser next */
3106 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003107 }
3108
3109 return LY_SUCCESS;
3110}
3111
David Sedlákaa98bba2019-09-12 11:52:14 +02003112/**
3113 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
3114 *
3115 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákaa98bba2019-09-12 11:52:14 +02003116 * @param[in] elem_type Type of element that is currently being parsed.
3117 * @param[out] arg Value to write to.
3118 *
3119 * @return LY_ERR values.
3120 */
3121static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003122yin_parse_extension_instance_arg(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **arg)
David Sedláke6284fc2019-09-10 11:57:02 +02003123{
David Sedlák071f7662019-09-12 02:02:51 +02003124 enum ly_stmt child;
David Sedláke6284fc2019-09-10 11:57:02 +02003125
Michal Vaskob36053d2020-03-26 15:49:30 +01003126 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3127
David Sedláke6284fc2019-09-10 11:57:02 +02003128 switch (elem_type) {
3129 case LY_STMT_ACTION:
3130 case LY_STMT_ANYDATA:
3131 case LY_STMT_ANYXML:
3132 case LY_STMT_ARGUMENT:
3133 case LY_STMT_BASE:
3134 case LY_STMT_BIT:
3135 case LY_STMT_CASE:
3136 case LY_STMT_CHOICE:
3137 case LY_STMT_CONTAINER:
3138 case LY_STMT_ENUM:
3139 case LY_STMT_EXTENSION:
3140 case LY_STMT_FEATURE:
3141 case LY_STMT_GROUPING:
3142 case LY_STMT_IDENTITY:
3143 case LY_STMT_IF_FEATURE:
3144 case LY_STMT_LEAF:
3145 case LY_STMT_LEAF_LIST:
3146 case LY_STMT_LIST:
3147 case LY_STMT_MODULE:
3148 case LY_STMT_NOTIFICATION:
3149 case LY_STMT_RPC:
3150 case LY_STMT_SUBMODULE:
3151 case LY_STMT_TYPE:
3152 case LY_STMT_TYPEDEF:
3153 case LY_STMT_UNITS:
3154 case LY_STMT_USES:
Michal Vaskob36053d2020-03-26 15:49:30 +01003155 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003156 break;
3157 case LY_STMT_AUGMENT:
3158 case LY_STMT_DEVIATION:
3159 case LY_STMT_REFINE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003160 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003161 break;
3162 case LY_STMT_CONFIG:
3163 case LY_STMT_DEFAULT:
3164 case LY_STMT_DEVIATE:
3165 case LY_STMT_ERROR_APP_TAG:
David Sedláke6284fc2019-09-10 11:57:02 +02003166 case LY_STMT_FRACTION_DIGITS:
3167 case LY_STMT_KEY:
3168 case LY_STMT_LENGTH:
3169 case LY_STMT_MANDATORY:
3170 case LY_STMT_MAX_ELEMENTS:
3171 case LY_STMT_MIN_ELEMENTS:
3172 case LY_STMT_MODIFIER:
3173 case LY_STMT_ORDERED_BY:
3174 case LY_STMT_PATH:
3175 case LY_STMT_PATTERN:
3176 case LY_STMT_POSITION:
3177 case LY_STMT_PREFIX:
3178 case LY_STMT_PRESENCE:
3179 case LY_STMT_RANGE:
3180 case LY_STMT_REQUIRE_INSTANCE:
3181 case LY_STMT_STATUS:
3182 case LY_STMT_VALUE:
3183 case LY_STMT_YANG_VERSION:
3184 case LY_STMT_YIN_ELEMENT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003185 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003186 break;
3187 case LY_STMT_IMPORT:
3188 case LY_STMT_INCLUDE:
3189 case LY_STMT_BELONGS_TO:
Michal Vaskob36053d2020-03-26 15:49:30 +01003190 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003191 break;
3192 case LY_STMT_INPUT:
3193 case LY_STMT_OUTPUT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003194 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003195 break;
3196 case LY_STMT_MUST:
3197 case LY_STMT_WHEN:
Michal Vaskob36053d2020-03-26 15:49:30 +01003198 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003199 break;
3200 case LY_STMT_NAMESPACE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003201 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003202 break;
3203 case LY_STMT_REVISION:
3204 case LY_STMT_REVISION_DATE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003205 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003206 break;
3207 case LY_STMT_UNIQUE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003208 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003209 break;
David Sedlák071f7662019-09-12 02:02:51 +02003210 /* argument is mapped to yin element */
3211 case LY_STMT_CONTACT:
3212 case LY_STMT_DESCRIPTION:
3213 case LY_STMT_ORGANIZATION:
3214 case LY_STMT_REFERENCE:
3215 case LY_STMT_ERROR_MESSAGE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003216 /* there shouldn't be any attribute, argument is supposed to be first subelement */
Michal Vaskob36053d2020-03-26 15:49:30 +01003217 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3218
3219 /* no content */
3220 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3221 if (ctx->xmlctx->ws_only) {
3222 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3223 }
3224 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3225 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
3226 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
David Sedlák071f7662019-09-12 02:02:51 +02003227 return LY_EVALID;
3228 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003229
3230 /* parse child element */
3231 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
3232 if ((elem_type == LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_VALUE) ||
3233 (elem_type != LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_TEXT)) {
3234 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3235 ly_stmt2str(elem_type));
3236 return LY_EVALID;
David Sedlákaa98bba2019-09-12 11:52:14 +02003237 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003238 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3239
3240 /* no attributes expected? TODO */
3241 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3242 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3243 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3244 }
3245
3246 /* load and save content */
3247 *arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3248 LY_CHECK_RET(!*arg, LY_EMEM);
3249
3250 /* load closing tag of subelement */
3251 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3252
3253 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3254 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3255 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3256 }*/
David Sedlákb0ca07d2019-09-11 11:54:05 +02003257 break;
David Sedláke6284fc2019-09-10 11:57:02 +02003258 default:
Michal Vaskob36053d2020-03-26 15:49:30 +01003259 LOGINT(ctx->xmlctx->ctx);
David Sedlák071f7662019-09-12 02:02:51 +02003260 return LY_EINT;
David Sedláke6284fc2019-09-10 11:57:02 +02003261 }
3262
David Sedlák071f7662019-09-12 02:02:51 +02003263 return LY_SUCCESS;
David Sedláke6284fc2019-09-10 11:57:02 +02003264}
3265
3266LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003267yin_parse_element_generic(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02003268{
3269 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003270 struct lysp_stmt *last = NULL, *new = NULL;
3271
Michal Vaskob36053d2020-03-26 15:49:30 +01003272 assert(ctx->xmlctx->status == LYXML_ELEMENT);
David Sedláke0ef1c62019-09-13 10:05:55 +02003273
3274 /* allocate new structure for element */
3275 *element = calloc(1, sizeof(**element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003276 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3277 (*element)->stmt = name2nsname(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len);
David Sedláke0ef1c62019-09-13 10:05:55 +02003278 LY_CHECK_ERR_GOTO(!(*element)->stmt, ret = LY_EMEM, cleanup);
David Sedláke0ef1c62019-09-13 10:05:55 +02003279
Michal Vaskob36053d2020-03-26 15:49:30 +01003280 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3281 ctx->xmlctx->prefix_len, parent);
David Sedlákb1a78352019-06-28 16:16:29 +02003282
3283 last = (*element)->child;
David Sedláke6284fc2019-09-10 11:57:02 +02003284 if ((*element)->kw == LY_STMT_NONE) {
3285 /* unrecognized element */
Michal Vaskob36053d2020-03-26 15:49:30 +01003286 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3287 ly_stmt2str(parent));
David Sedlákaa98bba2019-09-12 11:52:14 +02003288 ret = LY_EVALID;
3289 goto cleanup;
David Sedláke6284fc2019-09-10 11:57:02 +02003290 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3291 /* element is known yang keyword, which means argument can be parsed correctly. */
Michal Vaskob36053d2020-03-26 15:49:30 +01003292 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
David Sedlákaa98bba2019-09-12 11:52:14 +02003293 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003294 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01003295 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3296
David Sedlákaa98bba2019-09-12 11:52:14 +02003297 /* load attributes in generic way, save all attributes in linked list */
Michal Vaskob36053d2020-03-26 15:49:30 +01003298 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedláke6284fc2019-09-10 11:57:02 +02003299 new = calloc(1, sizeof(*last));
Michal Vaskob36053d2020-03-26 15:49:30 +01003300 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003301 if (!(*element)->child) {
3302 /* save first */
3303 (*element)->child = new;
3304 } else {
3305 last->next = new;
3306 }
3307 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003308
David Sedláke6284fc2019-09-10 11:57:02 +02003309 last->flags |= LYS_YIN_ATTR;
Michal Vaskob36053d2020-03-26 15:49:30 +01003310 last->stmt = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlákb0ca07d2019-09-11 11:54:05 +02003311 last->kw = LY_STMT_NONE;
David Sedláke6284fc2019-09-10 11:57:02 +02003312 /* attributes with prefix are ignored */
Michal Vaskob36053d2020-03-26 15:49:30 +01003313 if (!ctx->xmlctx->prefix) {
3314 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3315
3316 last->arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
David Sedlákaa98bba2019-09-12 11:52:14 +02003317 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003318 } else {
3319 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003320 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003321 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003322 }
3323 }
3324
Michal Vaskob36053d2020-03-26 15:49:30 +01003325 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3326 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3327 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3328 /* parse subelements */
3329 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
David Sedlákaa98bba2019-09-12 11:52:14 +02003330 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003331 if (!(*element)->child) {
3332 /* save first */
3333 (*element)->child = new;
3334 } else {
3335 last->next = new;
David Sedláka82ecff2019-08-16 10:51:48 +02003336 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003337 last = new;
David Sedlák169cc522019-08-15 13:23:45 +02003338
Michal Vaskob36053d2020-03-26 15:49:30 +01003339 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3340 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003341 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003342 } else {
3343 /* save element content */
3344 if (ctx->xmlctx->value_len) {
3345 (*element)->arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3346 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
3347 }
3348
3349 /* read closing tag */
3350 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003351 }
3352
David Sedlákb0ca07d2019-09-11 11:54:05 +02003353cleanup:
David Sedlákb0ca07d2019-09-11 11:54:05 +02003354 return ret;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003355}
3356
3357LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003358yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003359{
David Sedlák81497a32019-08-13 16:56:26 +02003360 LY_ERR ret = LY_SUCCESS;
3361 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003362 struct lysp_submodule *dup;
David Sedlák3b4db242018-10-19 16:11:01 +02003363
Michal Vaskob36053d2020-03-26 15:49:30 +01003364 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3365 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, LY_STMT_MODULE));
David Sedlák81497a32019-08-13 16:56:26 +02003366 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003367 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3368 LY_STMT_ANYXML, &mod->data, 0,
3369 LY_STMT_AUGMENT, &mod->augments, 0,
3370 LY_STMT_CHOICE, &mod->data, 0,
3371 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3372 LY_STMT_CONTAINER, &mod->data, 0,
3373 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3374 LY_STMT_DEVIATION, &mod->deviations, 0,
3375 LY_STMT_EXTENSION, &mod->extensions, 0,
3376 LY_STMT_FEATURE, &mod->features, 0,
3377 LY_STMT_GROUPING, &mod->groupings, 0,
3378 LY_STMT_IDENTITY, &mod->identities, 0,
3379 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3380 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3381 LY_STMT_LEAF, &mod->data, 0,
3382 LY_STMT_LEAF_LIST, &mod->data, 0,
3383 LY_STMT_LIST, &mod->data, 0,
3384 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3385 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3386 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3387 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3388 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3389 LY_STMT_REVISION, &mod->revs, 0,
3390 LY_STMT_RPC, &mod->rpcs, 0,
3391 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3392 LY_STMT_USES, &mod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003393 LY_STMT_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003394 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003395 ));
3396
Michal Vaskob36053d2020-03-26 15:49:30 +01003397 ret = yin_parse_content(ctx, subelems, 28, LY_STMT_MODULE, NULL, &mod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003398 subelems_deallocator(28, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003399 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003400
David Sedláked809f12019-09-13 10:15:11 +02003401 /* finalize parent pointers to the reallocated items */
3402 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
3403
3404 /* submodules share the namespace with the module names, so there must not be
3405 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003406 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, mod->mod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003407 if (dup) {
3408 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
3409 return LY_EVALID;
3410 }
3411
3412 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003413}
3414
3415LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003416yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003417{
David Sedlák81497a32019-08-13 16:56:26 +02003418 LY_ERR ret = LY_SUCCESS;
3419 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003420 struct lysp_submodule *dup;
David Sedlák298ff6d2019-07-26 14:29:03 +02003421
Michal Vaskob36053d2020-03-26 15:49:30 +01003422 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3423 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, LY_STMT_SUBMODULE));
David Sedlák81497a32019-08-13 16:56:26 +02003424 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003425 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3426 LY_STMT_ANYXML, &submod->data, 0,
3427 LY_STMT_AUGMENT, &submod->augments, 0,
3428 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3429 LY_STMT_CHOICE, &submod->data, 0,
3430 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3431 LY_STMT_CONTAINER, &submod->data, 0,
3432 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3433 LY_STMT_DEVIATION, &submod->deviations, 0,
3434 LY_STMT_EXTENSION, &submod->extensions, 0,
3435 LY_STMT_FEATURE, &submod->features, 0,
3436 LY_STMT_GROUPING, &submod->groupings, 0,
3437 LY_STMT_IDENTITY, &submod->identities, 0,
3438 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3439 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3440 LY_STMT_LEAF, &submod->data, 0,
3441 LY_STMT_LEAF_LIST, &submod->data, 0,
3442 LY_STMT_LIST, &submod->data, 0,
3443 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3444 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3445 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3446 LY_STMT_REVISION, &submod->revs, 0,
3447 LY_STMT_RPC, &submod->rpcs, 0,
3448 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3449 LY_STMT_USES, &submod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003450 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003451 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003452 ));
3453
Michal Vaskob36053d2020-03-26 15:49:30 +01003454 ret = yin_parse_content(ctx, subelems, 27, LY_STMT_SUBMODULE, NULL, &submod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003455 subelems_deallocator(27, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003456 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003457
David Sedláked809f12019-09-13 10:15:11 +02003458 /* finalize parent pointers to the reallocated items */
3459 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
3460
3461 /* submodules share the namespace with the module names, so there must not be
3462 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003463 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, submod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003464 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
3465 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
3466 return LY_EVALID;
3467 }
3468
3469 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003470}
3471
3472LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003473yin_parse_submodule(struct lys_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 +02003474{
Radek Krejcid6b76452019-09-03 17:03:03 +02003475 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003476 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003477 struct lysp_submodule *mod_p = NULL;
3478
3479 /* create context */
3480 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003481 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003482 (*yin_ctx)->format = LYS_IN_YIN;
3483 LY_CHECK_RET(lyxml_ctx_new(ctx, data, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003484
David Sedlák1b623122019-08-05 15:27:49 +02003485 /* map the typedefs and groupings list from main context to the submodule's context */
3486 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3487 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3488
David Sedlák8985a142019-07-31 16:43:06 +02003489 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003490 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
3491 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003492 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003493 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3494 ret = LY_EINVAL;
3495 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003496 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003497 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003498 ret = LY_EVALID;
3499 goto cleanup;
3500 }
3501
3502 mod_p = calloc(1, sizeof *mod_p);
3503 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3504 mod_p->parsing = 1;
3505
Michal Vaskob36053d2020-03-26 15:49:30 +01003506 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003507 LY_CHECK_GOTO(ret, cleanup);
3508
David Sedlákbf8a2b72019-08-14 16:48:10 +02003509 /* skip possible trailing whitespaces at end of the input */
Michal Vaskob36053d2020-03-26 15:49:30 +01003510 data = (*yin_ctx)->xmlctx->input;
3511 while (*data && isspace(*data)) {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003512 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003513 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003514 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003515 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 +02003516 ret = LY_EVALID;
3517 goto cleanup;
3518 }
3519
David Sedlák8985a142019-07-31 16:43:06 +02003520 mod_p->parsing = 0;
3521 *submod = mod_p;
3522
3523cleanup:
3524 if (ret) {
3525 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003526 yin_parser_ctx_free(*yin_ctx);
3527 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003528 }
David Sedlák8985a142019-07-31 16:43:06 +02003529 return ret;
3530}
3531
3532LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003533yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003534{
David Sedláke4889912018-11-02 09:52:40 +01003535 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003536 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003537 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003538
David Sedlák8985a142019-07-31 16:43:06 +02003539 /* create context */
3540 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003541 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003542 (*yin_ctx)->format = LYS_IN_YIN;
3543 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, data, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003544
David Sedlák8985a142019-07-31 16:43:06 +02003545 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003546 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
3547 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003548 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003549 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 +01003550 ret = LY_EINVAL;
3551 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003552 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003553 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003554 ret = LY_EVALID;
3555 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003556 }
3557
David Sedlák3017da42019-02-15 09:48:04 +01003558 /* allocate module */
3559 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003560 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003561 mod_p->mod = mod;
3562 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003563
David Sedlák00250342019-06-21 14:19:39 +02003564 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003565 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003566 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003567
David Sedlákbf8a2b72019-08-14 16:48:10 +02003568 /* skip possible trailing whitespaces at end of the input */
Michal Vaskob36053d2020-03-26 15:49:30 +01003569 data = (*yin_ctx)->xmlctx->input;
3570 while (*data && isspace(*data)) {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003571 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003572 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003573 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003574 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 +02003575 ret = LY_EVALID;
3576 goto cleanup;
3577 }
3578
David Sedlák3017da42019-02-15 09:48:04 +01003579 mod_p->parsing = 0;
3580 mod->parsed = mod_p;
3581
3582cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003583 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003584 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003585 yin_parser_ctx_free(*yin_ctx);
3586 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003587 }
David Sedlák2e411422018-12-17 02:35:39 +01003588 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003589}