blob: 0e8c7f92f747ef3ac267490b66cc4255cfeb9ceb [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 */
Radek Krejci535ea9f2020-05-29 16:01:05 +020014#include "parser_yin.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020015
David Sedlák3ffbc522019-07-02 17:49:28 +020016#include <assert.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020017#include <ctype.h>
18#include <errno.h>
19#include <stdarg.h>
20#include <stdbool.h>
David Sedlák3b4db242018-10-19 16:11:01 +020021#include <stdio.h>
22#include <stdlib.h>
David Sedlák872c7b42018-10-26 13:15:20 +020023#include <string.h>
David Sedlákf824ad52018-10-14 23:58:15 +020024
Radek Krejci535ea9f2020-05-29 16:01:05 +020025#include "common.h"
David Sedlákf824ad52018-10-14 23:58:15 +020026#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020027#include "dict.h"
Michal Vasko004d3152020-06-11 19:59:22 +020028#include "path.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020029#include "set.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020030#include "tree.h"
31#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020032#include "tree_schema_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020033#include "xml.h"
David Sedlák00250342019-06-21 14:19:39 +020034
David Sedlák2b214ac2019-06-06 16:11:03 +020035/**
36 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020037 *
David Sedlák2b214ac2019-06-06 16:11:03 +020038 * @param ns Namespace URI to check.
39 *
40 * @return true if ns equals YIN_NS_URI false otherwise.
41 */
42#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
43
David Sedlákf6251182019-06-06 10:22:13 +020044const char *const yin_attr_list[] = {
45 [YIN_ARG_NAME] = "name",
46 [YIN_ARG_TARGET_NODE] = "target-node",
47 [YIN_ARG_MODULE] = "module",
48 [YIN_ARG_VALUE] = "value",
49 [YIN_ARG_TEXT] = "text",
50 [YIN_ARG_CONDITION] = "condition",
51 [YIN_ARG_URI] = "uri",
52 [YIN_ARG_DATE] = "date",
53 [YIN_ARG_TAG] = "tag",
David Sedlák071f7662019-09-12 02:02:51 +020054 [YIN_ARG_NONE] = "none",
David Sedlákf6251182019-06-06 10:22:13 +020055};
56
Radek Krejcid6b76452019-09-03 17:03:03 +020057enum ly_stmt
Michal Vaskob36053d2020-03-26 15:49:30 +010058yin_match_keyword(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejcid6b76452019-09-03 17:03:03 +020059 const char *prefix, size_t prefix_len, enum ly_stmt parrent)
David Sedlák1bccdfa2019-06-17 15:55:27 +020060{
David Sedlák8f7a1172019-06-20 14:42:18 +020061 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +020062 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020063 const struct lyxml_ns *ns = NULL;
64
65 if (!name || name_len == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +020066 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +020067 }
68
Michal Vaskob36053d2020-03-26 15:49:30 +010069 ns = lyxml_ns_get(ctx->xmlctx, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +020070 if (ns) {
71 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +020072 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +020073 }
74 } else {
75 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +020076 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020077 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020078
David Sedlák8f7a1172019-06-20 14:42:18 +020079 start = name;
80 kw = lysp_match_kw(NULL, &name);
81
82 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +020083 /* 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 +020084 if (kw == LY_STMT_VALUE && parrent == LY_STMT_ERROR_MESSAGE) {
85 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +020086 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020087 return kw;
88 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020089 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +020090 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +020091 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +020092 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +020093 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020094 }
95}
96
David Sedlákc5b20842019-08-13 10:18:31 +020097enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +020098yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020099{
David Sedlákc5b20842019-08-13 10:18:31 +0200100 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200101 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200102 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200103
David Sedlák94de2aa2019-02-15 12:42:11 +0100104#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
105#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100106#define IF_ARG_PREFIX_END }
107
David Sedlák1c8b2702019-02-22 11:03:02 +0100108 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100109 case 'c':
110 already_read += 1;
111 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200112 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200113
David Sedlák94de2aa2019-02-15 12:42:11 +0100114 case 'd':
115 already_read += 1;
116 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200117 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200118
David Sedlák94de2aa2019-02-15 12:42:11 +0100119 case 'm':
120 already_read += 1;
121 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200122 break;
123
David Sedlák94de2aa2019-02-15 12:42:11 +0100124 case 'n':
125 already_read += 1;
126 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200127 break;
128
David Sedlák94de2aa2019-02-15 12:42:11 +0100129 case 't':
130 already_read += 1;
131 IF_ARG_PREFIX("a", 1)
132 IF_ARG("g", 1, YIN_ARG_TAG)
133 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
134 IF_ARG_PREFIX_END
135 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200136 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200137
David Sedlák94de2aa2019-02-15 12:42:11 +0100138 case 'u':
139 already_read += 1;
140 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200141 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200142
David Sedlák94de2aa2019-02-15 12:42:11 +0100143 case 'v':
144 already_read += 1;
145 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200146 break;
147 }
148
David Sedlákc10e7902018-12-17 02:17:59 +0100149 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200150 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200151 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200152 }
153
David Sedlák18730132019-03-15 15:51:34 +0100154#undef IF_ARG
155#undef IF_ARG_PREFIX
156#undef IF_ARG_PREFIX_END
157
David Sedlák872c7b42018-10-26 13:15:20 +0200158 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200159}
160
Radek Krejcid6b76452019-09-03 17:03:03 +0200161#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
162 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
163 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
164 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200165
Radek Krejcid6b76452019-09-03 17:03:03 +0200166#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 +0200167
David Sedlák26ea1432019-08-14 13:42:23 +0200168/**
169 * @brief Free subelems information allocated on heap.
170 *
171 * @param[in] count Size of subelems array.
172 * @param[in] subelems Subelems array to free.
173 */
David Sedlák81497a32019-08-13 16:56:26 +0200174static void
175subelems_deallocator(size_t count, struct yin_subelement *subelems)
176{
177 for(size_t i = 0; i < count; ++i) {
178 if (HAS_META(subelems[i].type)) {
179 free(subelems[i].dest);
180 }
181 }
182
183 free(subelems);
184}
185
David Sedlák26ea1432019-08-14 13:42:23 +0200186/**
187 * @brief Allocate subelems information on heap.
188 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200189 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200190 * @param[in] count Number of subelements.
191 * @param[in] parent Parent node if any.
192 * @param[out] result Allocated subelems array.
193 *
194 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
195 */
David Sedlák81497a32019-08-13 16:56:26 +0200196static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100197subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
David Sedlák81497a32019-08-13 16:56:26 +0200198 struct yin_subelement **result, ...)
199{
200 va_list ap;
201
202 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200203 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200204
205 va_start(ap, result);
206 for (size_t i = 0; i < count; ++i) {
207 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200208 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200209 /* DEST */
210 if (IS_NODE_ELEM((*result)[i].type)) {
211 struct tree_node_meta *node_meta = NULL;
212 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200213 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200214 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200215 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200216 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200217 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200218 struct import_meta *imp_meta = NULL;
219 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200220 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200221 imp_meta->prefix = va_arg(ap, const char *);
222 imp_meta->imports = va_arg(ap, struct lysp_import **);
223 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200224 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200225 struct include_meta *inc_meta = NULL;
226 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200227 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200228 inc_meta->name = va_arg(ap, const char *);
229 inc_meta->includes = va_arg(ap, struct lysp_include **);
230 (*result)[i].dest = inc_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200231 } else if ((*result)[i].type == LY_STMT_INPUT || (*result)[i].type == LY_STMT_OUTPUT) {
David Sedlák81497a32019-08-13 16:56:26 +0200232 struct inout_meta *inout_meta = NULL;
233 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200234 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200235 inout_meta->parent = parent;
236 inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
237 (*result)[i].dest = inout_meta;
238 } else {
239 (*result)[i].dest = va_arg(ap, void *);
240 }
241 /* FLAGS */
242 (*result)[i].flags = va_arg(ap, int);
243 }
244 va_end(ap);
245
246 return LY_SUCCESS;
247
David Sedlákbf8a2b72019-08-14 16:48:10 +0200248mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200249 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100250 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200251 return LY_EMEM;
252}
253
David Sedlák8f7a1172019-06-20 14:42:18 +0200254LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100255yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200256{
257 int prefix = 0;
258 unsigned int c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100259 size_t utf8_char_len, already_read = 0;
260 const char *val;
261
262 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
263
264 val = ctx->xmlctx->value;
265 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200266 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
267 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
268 already_read += utf8_char_len;
Michal Vaskob36053d2020-03-26 15:49:30 +0100269 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200270
271 switch (val_type) {
272 case Y_IDENTIF_ARG:
273 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
274 break;
275 case Y_PREF_IDENTIF_ARG:
276 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
277 break;
278 case Y_STR_ARG:
279 case Y_MAYBE_STR_ARG:
280 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
281 break;
282 }
283 }
284
285 return LY_SUCCESS;
286}
287
David Sedlákb4e44562019-07-04 15:42:12 +0200288/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100289 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200290 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200291 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200292 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
293 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200294 * @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 +0200295 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200296 * @param[in] current_element Identification of current element, used for logging.
297 *
298 * @return LY_ERR values.
299 */
300static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100301yin_parse_attribute(struct lys_yin_parser_ctx *ctx, enum yin_argument arg_type, const char **arg_val, enum yang_arg val_type,
302 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200303{
David Sedlákc5b20842019-08-13 10:18:31 +0200304 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200305 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200306
David Sedlák1bccdfa2019-06-17 15:55:27 +0200307 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100308 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200309 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100310 if (!ctx->xmlctx->prefix) {
311 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200312 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100313 /* skip it */
314 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200315 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200316 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
David Sedlák292763b2019-07-09 11:10:53 +0200317 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200318 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100319
320 /* go to value */
321 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
322 LY_CHECK_RET(yin_validate_value(ctx, val_type));
323 *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 +0200324 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200325 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100326 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
327 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200328 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200329 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100330 } else {
331 /* skip it */
332 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200333 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100334
335 /* next attribute */
336 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200337 }
338
David Sedlák292763b2019-07-09 11:10:53 +0200339 /* anything else than Y_MAYBE_STR_ARG is mandatory */
340 if (val_type != Y_MAYBE_STR_ARG && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100341 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
342 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200343 return LY_EVALID;
344 }
345
346 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200347}
348
David Sedlákd6e56892019-07-01 15:40:24 +0200349/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200350 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200351 *
352 * @param[in] type Type of wanted record.
353 * @param[in] array_size Size of array.
354 * @param[in] array Searched array.
355 *
356 * @return Pointer to desired record on success, NULL if element is not in the array.
357 */
David Sedlákb4e44562019-07-04 15:42:12 +0200358static struct yin_subelement *
Radek Krejci12b1c152019-09-05 16:20:48 +0200359get_record(enum ly_stmt type, size_t array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200360{
Radek Krejci12b1c152019-09-05 16:20:48 +0200361 for (unsigned int u = 0; u < array_size; ++u) {
362 if (array[u].type == type) {
363 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200364 }
365 }
David Sedlákd6e56892019-07-01 15:40:24 +0200366 return NULL;
367}
368
David Sedlákbba38e52019-07-09 15:20:01 +0200369/**
370 * @brief Helper function to check mandatory constraint of subelement.
371 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200372 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200373 * @param[in] subelem_info Array of information about subelements.
374 * @param[in] subelem_info_size Size of subelem_info array.
375 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
376 *
377 * @return LY_ERR values.
378 */
379static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100380yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200381 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200382{
David Sedlákb0faad82019-07-04 14:28:59 +0200383 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200384 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200385 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200386 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200387 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200388 return LY_EVALID;
389 }
390 }
391
392 return LY_SUCCESS;
393}
394
David Sedlákbba38e52019-07-09 15:20:01 +0200395/**
396 * @brief Helper function to check "first" constraint of subelement.
397 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200398 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200399 * @param[in] subelem_info Array of information about subelements.
400 * @param[in] subelem_info_size Size of subelem_info array.
401 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200402 * @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 +0200403 *
404 * @return LY_ERR values.
405 */
406static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100407yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200408 signed char subelem_info_size, enum ly_stmt current_element,
David Sedláke1a30302019-07-10 13:49:38 +0200409 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200410{
David Sedlákb0faad82019-07-04 14:28:59 +0200411 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200412 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200413 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
414 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200415 return LY_EVALID;
416 }
417 }
418
419 return LY_SUCCESS;
420}
421
David Sedlákbba38e52019-07-09 15:20:01 +0200422/**
David Sedlákb4e44562019-07-04 15:42:12 +0200423 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
424 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200425 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200426 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200427 * @param[in] kw Type of current element.
428 * @param[out] value Where value of attribute should be stored.
429 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200430 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200431 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200432 * @return LY_ERR values.
433 */
David Sedlákb4e44562019-07-04 15:42:12 +0200434static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100435yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
436 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200437{
Michal Vaskob36053d2020-03-26 15:49:30 +0100438 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
439 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200440 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200441 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200442 };
David Sedlákb4e44562019-07-04 15:42:12 +0200443
Michal Vaskob36053d2020-03-26 15:49:30 +0100444 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200445}
446
447/**
David Sedlák6542aed2019-08-14 10:47:43 +0200448 * @brief Parse path element.
449 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200450 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200451 * @param[in] kw Type of current element.
452 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200453 * @return LY_ERR values.
454 */
455static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100456yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200457{
Michal Vasko004d3152020-06-11 19:59:22 +0200458 LY_ERR ret;
459 const char *str_path;
460
461 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, &str_path, YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
462 ret = ly_path_parse(ctx->xmlctx->ctx, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
463 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
464 lydict_remove(ctx->xmlctx->ctx, str_path);
465 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200466 type->flags |= LYS_SET_PATH;
467
468 return LY_SUCCESS;
469}
470
471/**
David Sedlákd3983112019-07-12 11:20:56 +0200472 * @brief Parse pattern element.
473 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200474 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200475 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200476 * @return LY_ERR values.
477 */
478static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100479yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200480{
481 const char *real_value = NULL;
482 char *saved_value = NULL;
483 struct lysp_restr *restr;
484
Michal Vaskob36053d2020-03-26 15:49:30 +0100485 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
486 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
487 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 +0200488 size_t len = strlen(real_value);
489
490 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100491 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200492 memmove(saved_value + 1, real_value, len);
Michal Vaskob36053d2020-03-26 15:49:30 +0100493 FREE_STRING(ctx->xmlctx->ctx, real_value);
David Sedlákd3983112019-07-12 11:20:56 +0200494 saved_value[0] = 0x06;
495 saved_value[len + 1] = '\0';
Michal Vaskob36053d2020-03-26 15:49:30 +0100496 restr->arg = lydict_insert_zc(ctx->xmlctx->ctx, saved_value);
497 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200498 type->flags |= LYS_SET_PATTERN;
499
500 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200501 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
502 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
503 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
504 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
505 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
506 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákd3983112019-07-12 11:20:56 +0200507 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100508 return yin_parse_content(ctx, subelems, 6, LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200509}
510
David Sedlákc5b20842019-08-13 10:18:31 +0200511/**
512 * @brief Parse fraction-digits element.
513 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200514 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200515 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200516 * @return LY_ERR values.
517 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200518static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100519yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200520{
521 const char *temp_val = NULL;
522 char *ptr;
523 unsigned long int num;
524
Michal Vaskob36053d2020-03-26 15:49:30 +0100525 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
526 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 +0200527
528 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[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
534 errno = 0;
535 num = strtoul(temp_val, &ptr, 10);
536 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200537 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100538 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200539 return LY_EVALID;
540 }
541 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200542 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100543 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200544 return LY_EVALID;
545 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100546 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200547 type->fraction_digits = num;
548 type->flags |= LYS_SET_FRDIGITS;
549 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200550 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200551 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100552 return yin_parse_content(ctx, subelems, 1, LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200553}
554
David Sedlák07869a52019-07-12 14:28:19 +0200555/**
David Sedlák43801c92019-08-05 15:58:54 +0200556 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200557 *
558 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200559 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200560 * @return LY_ERR values.
561 */
David Sedlákca36c422019-07-12 12:47:55 +0200562static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100563yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200564{
David Sedlák07869a52019-07-12 14:28:19 +0200565 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200566
Michal Vaskob36053d2020-03-26 15:49:30 +0100567 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200568 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100569 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
570 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 +0200571 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100572 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200573 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200574
575 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200576 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
577 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
578 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
579 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
580 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
581 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákca36c422019-07-12 12:47:55 +0200582 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100583 return yin_parse_content(ctx, subelems, 6, LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200584}
585
586/**
587 * @brief Parse bit element.
588 *
589 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200590 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200591 * @return LY_ERR values.
592 */
593static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100594yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200595{
596 struct lysp_type_enum *en;
597
Michal Vaskob36053d2020-03-26 15:49:30 +0100598 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200599 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100600 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
601 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 +0200602 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
603
604 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200605 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
606 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
607 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
608 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
609 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
610 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák43801c92019-08-05 15:58:54 +0200611 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100612 return yin_parse_content(ctx, subelems, 6, LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200613}
614
David Sedlákd3983112019-07-12 11:20:56 +0200615/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200616 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
617 * more instances, such as base or if-feature.
618 *
619 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200620 * @param[in] kw Type of current element.
621 * @param[out] values Parsed values to add to.
622 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200623 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200624 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200625 * @return LY_ERR values.
626 */
627static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100628yin_parse_simple_elements(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char ***values, enum yin_argument arg_type,
629 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200630{
631 const char **value;
Michal Vaskob36053d2020-03-26 15:49:30 +0100632 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Radek Krejci7eb54ba2020-05-18 16:30:04 +0200633 LY_ARRAY_SIZE_TYPE index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200634 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200635 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200636 };
637
Michal Vaskob36053d2020-03-26 15:49:30 +0100638 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
639 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200640
Michal Vaskob36053d2020-03-26 15:49:30 +0100641 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200642}
643
644/**
David Sedlák6542aed2019-08-14 10:47:43 +0200645 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
646 *
647 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200648 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200649 * @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 +0200650 * @param[in] arg_type Expected type of attribute.
651 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200652 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200653 * @return LY_ERR values.
654 */
655static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100656yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
657 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200658{
659 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100660 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200661 arg_type, arg_val_type, exts));
662 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100663 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200664 arg_type, arg_val_type, exts));
665 }
666
667 return LY_SUCCESS;
668}
669
670/**
671 * @brief Parse base element.
672 *
673 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200674 * @param[in] parent Identification of parent element.
675 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200676 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200677 * @return LY_ERR values.
678 */
679static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100680yin_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 +0200681{
682 struct lysp_type *type = NULL;
683
Radek Krejcid6b76452019-09-03 17:03:03 +0200684 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200685 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100686 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
David Sedlák6542aed2019-08-14 10:47:43 +0200687 Y_PREF_IDENTIF_ARG, exts));
688 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200689 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100690 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200691 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
692 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100693 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200694 return LY_EINT;
695 }
696
697 return LY_SUCCESS;
698}
699
700/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200701 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200702 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200703 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100704 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200705 * @return LY_ERR values.
706 */
707static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100708yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200709{
710 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200711 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200712 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200713 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200714
715 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100716 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
717 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 +0200718 if (strcmp(temp_val, "true") == 0) {
719 type->require_instance = 1;
720 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200721 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
722 "require-instance", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +0100723 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200724 return LY_EVALID;
725 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100726 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200727
Michal Vaskob36053d2020-03-26 15:49:30 +0100728 return yin_parse_content(ctx, subelems, 1, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200729}
730
731/**
David Sedlákce77bf52019-07-11 16:59:31 +0200732 * @brief Parse modifier element.
733 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200734 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200735 * @param[in,out] pat Value to write to.
736 * @param[in,out] exts Extension instances to add to.
737 *
738 * @return LY_ERR values.
739 */
740static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100741yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200742{
David Sedlákd3983112019-07-12 11:20:56 +0200743 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200744 const char *temp_val;
745 char *modified_val;
746 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200747 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákce77bf52019-07-11 16:59:31 +0200748 };
749
Michal Vaskob36053d2020-03-26 15:49:30 +0100750 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
751 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 +0200752 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200753 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
754 "modifier", "invert-match");
Michal Vaskob36053d2020-03-26 15:49:30 +0100755 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200756 return LY_EVALID;
757 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100758 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200759
760 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200761 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100762 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200763 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100764 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200765
766 /* modify the new value */
767 modified_val[0] = 0x15;
Michal Vaskob36053d2020-03-26 15:49:30 +0100768 *pat = lydict_insert_zc(ctx->xmlctx->ctx, modified_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200769
Michal Vaskob36053d2020-03-26 15:49:30 +0100770 return yin_parse_content(ctx, subelems, 1, LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200771}
772
773/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200774 * @brief Parse a restriction element (length, range or one instance of must).
775 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200776 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200777 * @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 +0200778 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200779 */
780static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100781yin_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 +0200782{
Radek Krejcid6b76452019-09-03 17:03:03 +0200783 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
David Sedlákb7296dd2019-07-11 14:58:38 +0200784 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200785 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
786 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
787 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
788 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
789 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200790 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200791 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200792 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200793
Michal Vaskob36053d2020-03-26 15:49:30 +0100794 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
795 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
796
797 return yin_parse_content(ctx, subelems, 5, restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200798}
799
800/**
David Sedlák6542aed2019-08-14 10:47:43 +0200801 * @brief Parse range element.
802 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200803 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200804 * @param[out] type Type structure to store parsed value and flags.
805 *
806 * @return LY_ERR values.
807 */
808static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100809yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200810{
811 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100812 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
813 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
David Sedlák6542aed2019-08-14 10:47:43 +0200814 type->flags |= LYS_SET_RANGE;
815
816 return LY_SUCCESS;
817}
818
819/**
820 * @brief Parse length element.
821 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200822 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200823 * @param[out] type Type structure to store parsed value and flags.
824 *
825 * @return LY_ERR values.
826 */
827static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100828yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200829{
830 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100831 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
832 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200833 type->flags |= LYS_SET_LENGTH;
834
835 return LY_SUCCESS;
836}
837
838/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200839 * @brief Parse must element.
840 *
841 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200842 * @param[in,out] restrs Restrictions to add to.
843 *
844 * @return LY_ERR values.
845 */
846static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100847yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200848{
849 struct lysp_restr *restr;
850
Michal Vaskob36053d2020-03-26 15:49:30 +0100851 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
852 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200853}
854
855/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200856 * @brief Parse position or value element.
857 *
858 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200859 * @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 +0200860 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200861 *
862 * @return LY_ERR values.
863 */
864static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100865yin_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 +0200866{
Radek Krejcid6b76452019-09-03 17:03:03 +0200867 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +0200868 const char *temp_val = NULL;
869 char *ptr;
870 long int num;
871 unsigned long int unum;
872
873 /* set value flag */
874 enm->flags |= LYS_SET_VALUE;
875
876 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +0100877 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
878 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
David Sedlákae5378f2019-07-17 11:37:59 +0200879 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
Radek Krejcid6b76452019-09-03 17:03:03 +0200880 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200881 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 +0200882 goto error;
883 }
884
885 /* convert value */
886 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +0200887 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200888 num = strtol(temp_val, &ptr, 10);
889 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200890 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 +0200891 goto error;
892 }
893 } else {
894 unum = strtoul(temp_val, &ptr, 10);
895 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200896 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 +0200897 goto error;
898 }
899 }
900 /* check if whole argument value was converted */
901 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200902 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 +0200903 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200904 }
905 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +0200906 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 +0200907 goto error;
908 }
909 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +0200910 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200911 enm->value = num;
912 } else {
913 enm->value = unum;
914 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100915 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +0200916
917 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200918 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200919 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200920 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100921 return yin_parse_content(ctx, subelems, 1, kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +0200922
David Sedlákbf8a2b72019-08-14 16:48:10 +0200923error:
Michal Vaskob36053d2020-03-26 15:49:30 +0100924 FREE_STRING(ctx->xmlctx->ctx, temp_val);
925 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +0200926}
927
David Sedlák05404f62019-07-24 14:11:53 +0200928/**
929 * @brief Parse belongs-to element.
930 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200931 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +0200932 * @param[out] submod Structure of submodule that is being parsed.
933 * @param[in,out] exts Extension instances to add to.
934 *
935 * @return LY_ERR values
936 */
937static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100938yin_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 +0200939{
940 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200941 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
942 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák05404f62019-07-24 14:11:53 +0200943 };
David Sedlák05404f62019-07-24 14:11:53 +0200944
Michal Vaskob36053d2020-03-26 15:49:30 +0100945 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
946 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
947
948 return yin_parse_content(ctx, subelems, 2, LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +0200949}
950
David Sedlák5545f5d2019-07-11 11:55:16 +0200951/**
David Sedlákc1771b12019-07-10 15:55:46 +0200952 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +0200953 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +0200954 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200955 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200956 * @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 +0200957 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200958 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200959 *
960 * @return LY_ERR values.
961 */
962static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100963yin_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 +0200964{
Radek Krejcid6b76452019-09-03 17:03:03 +0200965 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 +0200966
David Sedlák968ac342019-07-11 15:17:59 +0200967 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200968 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
969 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +0200970 };
David Sedlákdf2a9732019-08-07 13:23:16 +0200971 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100972 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
973 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 +0200974
David Sedlákdf2a9732019-08-07 13:23:16 +0200975 /* parse content */
Michal Vaskob36053d2020-03-26 15:49:30 +0100976 return yin_parse_content(ctx, subelems, 2, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200977}
978
979/**
David Sedlákc1771b12019-07-10 15:55:46 +0200980 * @brief Parse error-message element.
981 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200982 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +0200983 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200984 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +0200985 *
986 * @return LY_ERR values.
987 */
988static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100989yin_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 +0200990{
David Sedlák968ac342019-07-11 15:17:59 +0200991 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200992 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
993 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +0200994 };
David Sedlákc1771b12019-07-10 15:55:46 +0200995
David Sedlákdf2a9732019-08-07 13:23:16 +0200996 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100997 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
998 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 +0200999
Michal Vaskob36053d2020-03-26 15:49:30 +01001000 return yin_parse_content(ctx, subelems, 2, LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001001}
1002
1003/**
David Sedlák6542aed2019-08-14 10:47:43 +02001004 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001005 *
1006 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001007 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001008 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001009 *
1010 * @return LY_ERR values.
1011 */
1012static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001013yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001014{
David Sedlák6542aed2019-08-14 10:47:43 +02001015 struct lysp_type *type = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +02001016 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001017 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001018 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001019 type = *((struct lysp_type **)subinfo->dest);
1020 } else {
1021 type = (struct lysp_type *)subinfo->dest;
1022 }
1023 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001024 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001025 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001026 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001027 type->flags |= LYS_SET_TYPE;
1028 type = nested_type;
1029 }
David Sedlák374d2b32019-07-17 15:06:55 +02001030 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001031 {LY_STMT_BASE, type, 0},
1032 {LY_STMT_BIT, type, 0},
1033 {LY_STMT_ENUM, type, 0},
1034 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1035 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1036 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1037 {LY_STMT_PATTERN, type, 0},
1038 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1039 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1040 {LY_STMT_TYPE, type},
1041 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák374d2b32019-07-17 15:06:55 +02001042 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001043
1044 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1045 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1046 return yin_parse_content(ctx, subelems, 11, LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001047}
1048
David Sedlák1af868e2019-07-17 17:03:14 +02001049/**
1050 * @brief Parse max-elements element.
1051 *
1052 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001053 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001054 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001055 * @param[in,out] exts Extension instances to add to.
1056 *
1057 * @return LY_ERR values.
1058 */
1059static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001060yin_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 +02001061{
1062 const char *temp_val = NULL;
1063 char *ptr;
1064 unsigned long int num;
1065 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001066 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák1af868e2019-07-17 17:03:14 +02001067 };
David Sedlák374d2b32019-07-17 15:06:55 +02001068
David Sedlák1af868e2019-07-17 17:03:14 +02001069 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001070 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1071 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 +02001072 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 +02001073 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001074 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001075 return LY_EVALID;
1076 }
1077
1078 if (strcmp(temp_val, "unbounded")) {
1079 errno = 0;
1080 num = strtoul(temp_val, &ptr, 10);
1081 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001082 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001083 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001084 return LY_EVALID;
1085 }
1086 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001087 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001088 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001089 return LY_EVALID;
1090 }
1091 *max = num;
1092 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001093 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1094 return yin_parse_content(ctx, subelems, 1, LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001095}
David Sedlák374d2b32019-07-17 15:06:55 +02001096
1097/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001098 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001099 *
1100 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001101 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001102 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001103 * @param[in,out] exts Extension instances to add to.
1104 *
1105 * @return LY_ERR values.
1106 */
1107static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001108yin_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 +02001109{
1110 const char *temp_val = NULL;
1111 char *ptr;
1112 unsigned long int num;
1113 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001114 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák09e18c92019-07-18 11:17:11 +02001115 };
1116
1117 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001118 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1119 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 +02001120
1121 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\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
1127 errno = 0;
1128 num = strtoul(temp_val, &ptr, 10);
1129 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001130 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001131 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001132 return LY_EVALID;
1133 }
1134 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001135 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001136 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001137 return LY_EVALID;
1138 }
1139 *min = num;
Michal Vaskob36053d2020-03-26 15:49:30 +01001140 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1141 return yin_parse_content(ctx, subelems, 1, LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001142}
1143
David Sedláka2dad212019-07-18 12:45:19 +02001144/**
1145 * @brief Parse min-elements or max-elements element.
1146 *
1147 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001148 * @param[in] parent Identification of parent element.
1149 * @param[in] current Identification of current element.
1150 * @param[in] dest Where the parsed value and flags should be stored.
1151 *
1152 * @return LY_ERR values.
1153 */
David Sedlák09e18c92019-07-18 11:17:11 +02001154static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001155yin_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 +02001156{
Radek Krejcid6b76452019-09-03 17:03:03 +02001157 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1158 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 +02001159 uint32_t *lim;
1160 uint16_t *flags;
1161 struct lysp_ext_instance **exts;
1162
Radek Krejcid6b76452019-09-03 17:03:03 +02001163 if (parent == LY_STMT_LEAF_LIST) {
1164 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 +02001165 flags = &((struct lysp_node_leaflist *)dest)->flags;
1166 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001167 } else if (parent == LY_STMT_REFINE) {
1168 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001169 flags = &((struct lysp_refine *)dest)->flags;
1170 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001171 } else if (parent == LY_STMT_LIST) {
1172 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 +02001173 flags = &((struct lysp_node_list *)dest)->flags;
1174 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001175 } else {
1176 lim = ((struct minmax_dev_meta *)dest)->lim;
1177 flags = ((struct minmax_dev_meta *)dest)->flags;
1178 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001179 }
1180
Radek Krejcid6b76452019-09-03 17:03:03 +02001181 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001182 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001183 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001184 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001185 }
1186
1187 return LY_SUCCESS;
1188}
1189
1190/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001191 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001192 *
1193 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001194 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001195 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001196 *
1197 * @return LY_ERR values.
1198 */
1199static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001200yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001201{
1202 const char *temp_val;
1203 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001204 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedláka2dad212019-07-18 12:45:19 +02001205 };
1206
Michal Vaskob36053d2020-03-26 15:49:30 +01001207 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1208 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 +02001209 if (strcmp(temp_val, "system") == 0) {
1210 *flags |= LYS_ORDBY_SYSTEM;
1211 } else if (strcmp(temp_val, "user") == 0) {
1212 *flags |= LYS_ORDBY_USER;
1213 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001214 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1215 "ordered-by", "system", "user");
Michal Vaskob36053d2020-03-26 15:49:30 +01001216 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001217 return LY_EVALID;
1218 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001219 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001220
Michal Vaskob36053d2020-03-26 15:49:30 +01001221 return yin_parse_content(ctx, subelems, 1, LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001222}
1223
1224/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001225 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001226 *
1227 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001228 * @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 +02001229 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001230 *
1231 * @return LY_ERR values.
1232 */
1233static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001234yin_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 +02001235{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001236 struct lysp_node_anydata *any;
1237
David Sedlák8d552d62019-08-06 15:29:05 +02001238 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001239 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001240 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001241 any->parent = node_meta->parent;
1242
David Sedlákbf8a2b72019-08-14 16:48:10 +02001243 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001244 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1245 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 +02001246
1247 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001248 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1249 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1250 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1251 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1252 {LY_STMT_MUST, &any->musts, 0},
1253 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1254 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1255 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1256 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8a83bbb2019-07-18 14:46:00 +02001257 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001258 return yin_parse_content(ctx, subelems, 9, any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001259}
1260
1261/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001262 * @brief parse leaf element.
1263 *
1264 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001265 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001266 *
1267 * @return LY_ERR values.
1268 */
1269static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001270yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001271{
David Sedlák203ca3a2019-07-18 15:26:25 +02001272 struct lysp_node_leaf *leaf;
1273
David Sedlák8d552d62019-08-06 15:29:05 +02001274 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001275 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001276 leaf->nodetype = LYS_LEAF;
1277 leaf->parent = node_meta->parent;
1278
David Sedlák203ca3a2019-07-18 15:26:25 +02001279 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001280 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1281 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 +02001282
1283 /* parse content */
1284 struct yin_subelement subelems[12] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001285 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1286 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1287 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1288 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1289 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1290 {LY_STMT_MUST, &leaf->musts, 0},
1291 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1292 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1293 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1294 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1295 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1296 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001297 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001298 return yin_parse_content(ctx, subelems, 12, LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001299}
1300
1301/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001302 * @brief Parse leaf-list element.
1303 *
1304 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001305 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001306 *
1307 * @return LY_ERR values.
1308 */
1309static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001310yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001311{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001312 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001313
Michal Vaskob36053d2020-03-26 15:49:30 +01001314 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001315
David Sedlákc3da3ef2019-07-19 12:56:08 +02001316 llist->nodetype = LYS_LEAFLIST;
1317 llist->parent = node_meta->parent;
1318
David Sedlákc3da3ef2019-07-19 12:56:08 +02001319 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001320 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1321 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 +02001322
1323 /* parse content */
1324 struct yin_subelement subelems[14] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001325 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1326 {LY_STMT_DEFAULT, &llist->dflts, 0},
1327 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1328 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1329 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1330 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1331 {LY_STMT_MUST, &llist->musts, 0},
1332 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1333 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1334 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1335 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1336 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1337 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1338 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001339 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001340 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001341
David Sedlákbf8a2b72019-08-14 16:48:10 +02001342 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001343 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001344 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001345 return LY_EVALID;
1346 }
1347 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001348 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001349 return LY_EVALID;
1350 }
1351
1352 return LY_SUCCESS;
1353}
1354
1355/**
David Sedlák04e17b22019-07-19 15:29:48 +02001356 * @brief Parse typedef element.
1357 *
1358 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001359 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001360 *
1361 * @return LY_ERR values.
1362 */
1363static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001364yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001365{
1366 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001367 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vaskob36053d2020-03-26 15:49:30 +01001368 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001369
1370 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001371 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1372 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 +02001373
1374 /* parse content */
1375 struct yin_subelement subelems[7] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001376 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1377 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1378 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1379 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1380 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1381 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1382 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001383 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001384 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001385
1386 /* store data for collision check */
Michal Vasko1bf09392020-03-27 12:38:10 +01001387 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 +02001388 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0) == -1, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001389 }
1390
1391 return LY_SUCCESS;
1392}
1393
1394/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001395 * @brief Parse refine element.
1396 *
1397 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001398 * @param[in,out] refines Refines to add to.
1399 *
1400 * @return LY_ERR values.
1401 */
1402static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001403yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001404{
1405 struct lysp_refine *rf;
1406
1407 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001408 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001409
1410 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001411 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1412 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1413 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001414
1415 /* parse content */
1416 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001417 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1418 {LY_STMT_DEFAULT, &rf->dflts, 0},
1419 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1420 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
1421 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1422 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1423 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1424 {LY_STMT_MUST, &rf->musts, 0},
1425 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1426 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1427 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001428 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001429 return yin_parse_content(ctx, subelems, 11, LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001430}
1431
1432/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001433 * @brief Parse uses element.
1434 *
1435 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001436 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001437 *
1438 * @return LY_ERR values.
1439 */
1440static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001441yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001442{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001443 struct lysp_node_uses *uses;
1444
David Sedlák8d552d62019-08-06 15:29:05 +02001445 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001446 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001447 uses->nodetype = LYS_USES;
1448 uses->parent = node_meta->parent;
1449
David Sedlák0d6de5a2019-07-22 13:25:44 +02001450 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001451 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1452 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 +02001453
1454 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001455 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001456 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001457 {LY_STMT_AUGMENT, &augments, 0},
1458 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1459 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1460 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1461 {LY_STMT_REFINE, &uses->refines, 0},
1462 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1463 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1464 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001465 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001466 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001467 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1468
1469 return LY_SUCCESS;
1470}
1471
1472/**
David Sedlákaa854b02019-07-22 14:17:10 +02001473 * @brief Parse revision element.
1474 *
1475 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001476 * @param[in,out] revs Parsed revisions to add to.
1477 *
1478 * @return LY_ERR values.
1479 */
1480static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001481yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001482{
1483 struct lysp_revision *rev;
1484 const char *temp_date = NULL;
1485
1486 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001487 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001488
1489 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001490 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1491 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 +02001492 /* check value */
1493 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001494 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001495 return LY_EVALID;
1496 }
1497 strcpy(rev->date, temp_date);
Michal Vaskob36053d2020-03-26 15:49:30 +01001498 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001499
1500 /* parse content */
1501 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001502 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1503 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1504 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001505 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001506 return yin_parse_content(ctx, subelems, 3, LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001507}
1508
David Sedlák5e13dea2019-07-22 16:06:45 +02001509/**
1510 * @brief Parse include element.
1511 *
1512 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001513 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1514 *
1515 * @return LY_ERR values.
1516 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001517static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001518yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001519{
1520 struct lysp_include *inc;
1521
1522 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001523 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001524
1525 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001526 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1527 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 +02001528
1529 /* submodules share the namespace with the module names, so there must not be
1530 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001531 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 +02001532 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001533 return LY_EVALID;
1534 }
1535
1536 /* parse content */
1537 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001538 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1539 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1540 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1541 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák0c2bab92019-07-22 15:33:19 +02001542 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001543 return yin_parse_content(ctx, subelems, 4, LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001544}
1545
David Sedlákaa854b02019-07-22 14:17:10 +02001546/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001547 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001548 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001549 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001550 * @param[in,out] rev Array to store the parsed value in.
1551 * @param[in,out] exts Extension instances to add to.
1552 *
1553 * @return LY_ERR values.
1554 */
1555static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001556yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001557{
1558 const char *temp_rev;
1559 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001560 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001561 };
1562
Michal Vaskob36053d2020-03-26 15:49:30 +01001563 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1564 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 +02001565 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 +01001566 FREE_STRING(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001567
1568 strcpy(rev, temp_rev);
Michal Vaskob36053d2020-03-26 15:49:30 +01001569 FREE_STRING(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001570
Michal Vaskob36053d2020-03-26 15:49:30 +01001571 return yin_parse_content(ctx, subelems, 1, LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001572}
1573
1574/**
1575 * @brief Parse config element.
1576 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001577 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001578 * @param[in,out] flags Flags to add to.
1579 * @param[in,out] exts Extension instances to add to.
1580 *
1581 * @return LY_ERR values.
1582 */
1583static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001584yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001585{
1586 const char *temp_val = NULL;
1587 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001588 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001589 };
1590
Michal Vaskob36053d2020-03-26 15:49:30 +01001591 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1592 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 +02001593 if (strcmp(temp_val, "true") == 0) {
1594 *flags |= LYS_CONFIG_W;
1595 } else if (strcmp(temp_val, "false") == 0) {
1596 *flags |= LYS_CONFIG_R;
1597 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001598 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
1599 "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001600 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001601 return LY_EVALID;
1602 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001603 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001604
Michal Vaskob36053d2020-03-26 15:49:30 +01001605 return yin_parse_content(ctx, subelems, 1, LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001606}
1607
1608/**
1609 * @brief Parse yang-version element.
1610 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001611 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001612 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001613 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001614 *
1615 * @return LY_ERR values.
1616 */
1617static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001618yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001619{
1620 const char *temp_version = NULL;
1621 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001622 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001623 };
1624
Michal Vaskob36053d2020-03-26 15:49:30 +01001625 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1626 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 +02001627 if (strcmp(temp_version, "1.0") == 0) {
1628 *version = LYS_VERSION_1_0;
1629 } else if (strcmp(temp_version, "1.1") == 0) {
1630 *version = LYS_VERSION_1_1;
1631 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001632 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
1633 "yang-version", "1.0", "1.1");
Michal Vaskob36053d2020-03-26 15:49:30 +01001634 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001635 return LY_EVALID;
1636 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001637 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001638 ctx->mod_version = *version;
1639
Michal Vaskob36053d2020-03-26 15:49:30 +01001640 return yin_parse_content(ctx, subelems, 1, LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001641}
1642
1643/**
1644 * @brief Parse import element.
1645 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001646 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001647 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1648 *
1649 * @return LY_ERR values.
1650 */
1651static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001652yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001653{
1654 struct lysp_import *imp;
1655 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001656 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001657
1658 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001659 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1660 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1661 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1662 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1663 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001664 };
1665
1666 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001667 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1668 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
1669 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001670 /* check prefix validity */
1671 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1672
1673 return LY_SUCCESS;
1674}
1675
1676/**
1677 * @brief Parse mandatory element.
1678 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001679 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001680 * @param[in,out] flags Flags to add to.
1681 * @param[in,out] exts Extension instances to add to.
1682 *
1683 * @return LY_ERR values.
1684 */
1685static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001686yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001687{
1688 const char *temp_val = NULL;
1689 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001690 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001691 };
1692
Michal Vaskob36053d2020-03-26 15:49:30 +01001693 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1694 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 +02001695 if (strcmp(temp_val, "true") == 0) {
1696 *flags |= LYS_MAND_TRUE;
1697 } else if (strcmp(temp_val, "false") == 0) {
1698 *flags |= LYS_MAND_FALSE;
1699 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001700 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1701 "mandatory", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001702 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001703 return LY_EVALID;
1704 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001705 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001706
Michal Vaskob36053d2020-03-26 15:49:30 +01001707 return yin_parse_content(ctx, subelems, 1, LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001708}
1709
1710/**
1711 * @brief Parse status element.
1712 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001713 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001714 * @param[in,out] flags Flags to add to.
1715 * @param[in,out] exts Extension instances to add to.
1716 *
1717 * @return LY_ERR values.
1718 */
1719static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001720yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001721{
1722 const char *value = NULL;
1723 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001724 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001725 };
1726
Michal Vaskob36053d2020-03-26 15:49:30 +01001727 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1728 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 +02001729 if (strcmp(value, "current") == 0) {
1730 *flags |= LYS_STATUS_CURR;
1731 } else if (strcmp(value, "deprecated") == 0) {
1732 *flags |= LYS_STATUS_DEPRC;
1733 } else if (strcmp(value, "obsolete") == 0) {
1734 *flags |= LYS_STATUS_OBSLT;
1735 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001736 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
1737 "status", "current", "deprecated", "obsolete");
Michal Vaskob36053d2020-03-26 15:49:30 +01001738 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001739 return LY_EVALID;
1740 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001741 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001742
Michal Vaskob36053d2020-03-26 15:49:30 +01001743 return yin_parse_content(ctx, subelems, 1, LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001744}
1745
1746/**
1747 * @brief Parse when element.
1748 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001749 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001750 * @param[out] when_p When pointer to parse to.
1751 */
1752static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001753yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001754{
1755 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001756 LY_ERR ret = LY_SUCCESS;
1757
David Sedlákdfbbb442019-08-06 16:33:21 +02001758 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001759 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
1760 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1761 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001762 LY_CHECK_ERR_RET(ret, free(when), ret);
1763
David Sedlákdfbbb442019-08-06 16:33:21 +02001764 *when_p = when;
1765 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001766 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1767 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1768 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001769 };
1770
Michal Vaskob36053d2020-03-26 15:49:30 +01001771 return yin_parse_content(ctx, subelems, 3, LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001772}
1773
1774/**
1775 * @brief Parse yin-elemenet element.
1776 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001777 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001778 * @param[in,out] data Data to read from, always moved to currently handled position.
1779 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001780 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001781 *
1782 * @return LY_ERR values.
1783 */
1784static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001785yin_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 +02001786{
1787 const char *temp_val = NULL;
1788 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001789 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001790 };
1791
Michal Vaskob36053d2020-03-26 15:49:30 +01001792 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1793 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 +02001794 if (strcmp(temp_val, "true") == 0) {
1795 *flags |= LYS_YINELEM_TRUE;
1796 } else if (strcmp(temp_val, "false") == 0) {
1797 *flags |= LYS_YINELEM_FALSE;
1798 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001799 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1800 "yin-element", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001801 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001802 return LY_EVALID;
1803 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001804 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001805
Michal Vaskob36053d2020-03-26 15:49:30 +01001806 return yin_parse_content(ctx, subelems, 1, LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001807}
1808
1809/**
1810 * @brief Parse argument element.
1811 *
Michal Vaskob36053d2020-03-26 15:49:30 +01001812 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001813 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1814 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001815 *
1816 * @return LY_ERR values.
1817 */
1818static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001819yin_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 +02001820{
1821 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001822 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1823 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001824 };
1825
Michal Vaskob36053d2020-03-26 15:49:30 +01001826 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1827 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 +02001828
Michal Vaskob36053d2020-03-26 15:49:30 +01001829 return yin_parse_content(ctx, subelems, 2, LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001830}
1831
1832/**
1833 * @brief Parse the extension statement.
1834 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001835 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001836 * @param[in,out] extensions Extensions to add to.
1837 *
1838 * @return LY_ERR values.
1839 */
1840static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001841yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02001842{
1843 struct lysp_ext *ex;
Michal Vaskob36053d2020-03-26 15:49:30 +01001844 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
1845 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1846 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 +02001847
1848 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1849 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001850 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1851 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1852 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1853 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1854 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001855 };
1856
Michal Vaskob36053d2020-03-26 15:49:30 +01001857 return yin_parse_content(ctx, subelems, 5, LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001858}
1859
1860/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001861 * @brief Parse feature element.
1862 *
1863 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001864 * @param[in,out] features Features to add to.
1865 *
1866 * @return LY_ERR values.
1867 */
1868static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001869yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02001870{
1871 struct lysp_feature *feat;
1872
1873 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01001874 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02001875
1876 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001877 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1878 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 +02001879
1880 /* parse content */
1881 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001882 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1883 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
1884 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1885 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1886 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák5e13dea2019-07-22 16:06:45 +02001887 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001888 return yin_parse_content(ctx, subelems, 5, LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02001889}
1890
1891/**
David Sedlák28794f22019-07-22 16:45:00 +02001892 * @brief Parse identity element.
1893 *
1894 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02001895 * @param[in,out] identities Identities to add to.
1896 *
1897 * @return LY_ERR values.
1898 */
1899static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001900yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02001901{
1902 struct lysp_ident *ident;
1903
1904 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01001905 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02001906
1907 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001908 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1909 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 +02001910
1911 /* parse content */
1912 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001913 {LY_STMT_BASE, &ident->bases, 0},
1914 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
1915 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
1916 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
1917 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
1918 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák28794f22019-07-22 16:45:00 +02001919 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001920 return yin_parse_content(ctx, subelems, 6, LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02001921}
1922
1923/**
David Sedlákaf536aa2019-07-23 13:42:23 +02001924 * @brief Parse list element.
1925 *
1926 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001927 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02001928 *
1929 * @return LY_ERR values.
1930 */
1931static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001932yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02001933{
David Sedlákaf536aa2019-07-23 13:42:23 +02001934 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02001935 LY_ERR ret = LY_SUCCESS;
1936 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02001937
Michal Vaskob36053d2020-03-26 15:49:30 +01001938 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02001939 list->nodetype = LYS_LIST;
1940 list->parent = node_meta->parent;
1941
David Sedlákaf536aa2019-07-23 13:42:23 +02001942 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001943 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1944 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 +02001945
1946 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02001947 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02001948 LY_STMT_ACTION, &list->actions, 0,
1949 LY_STMT_ANYDATA, &list->child, 0,
1950 LY_STMT_ANYXML, &list->child, 0,
1951 LY_STMT_CHOICE, &list->child, 0,
1952 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
1953 LY_STMT_CONTAINER, &list->child, 0,
1954 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
1955 LY_STMT_GROUPING, &list->groupings, 0,
1956 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
1957 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
1958 LY_STMT_LEAF, &list->child, 0,
1959 LY_STMT_LEAF_LIST, &list->child, 0,
1960 LY_STMT_LIST, &list->child, 0,
1961 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
1962 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
1963 LY_STMT_MUST, &list->musts, 0,
1964 LY_STMT_NOTIFICATION, &list->notifs, 0,
1965 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
1966 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
1967 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
1968 LY_STMT_TYPEDEF, &list->typedefs, 0,
1969 LY_STMT_UNIQUE, &list->uniques, 0,
1970 LY_STMT_USES, &list->child, 0,
1971 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
1972 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02001973 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01001974 ret = yin_parse_content(ctx, subelems, 25, LY_STMT_LIST, NULL, &list->exts);
David Sedlák81497a32019-08-13 16:56:26 +02001975 subelems_deallocator(25, subelems);
1976 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02001977
1978 /* finalize parent pointers to the reallocated items */
1979 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
1980
1981 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001982 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02001983 return LY_EVALID;
1984 }
1985
1986 return LY_SUCCESS;
1987}
1988
1989/**
David Sedlák031b9e72019-07-23 15:19:37 +02001990 * @brief Parse notification element.
1991 *
1992 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001993 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02001994 *
1995 * @return LY_ERR values.
1996 */
1997static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001998yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02001999{
2000 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002001 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002002 LY_ERR ret = LY_SUCCESS;
2003 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002004
2005 /* allocate new notification */
Michal Vaskob36053d2020-03-26 15:49:30 +01002006 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002007 notif->nodetype = LYS_NOTIF;
2008 notif->parent = notif_meta->parent;
2009
2010 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002011 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2012 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 +02002013
2014 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002015 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002016 LY_STMT_ANYDATA, &notif->data, 0,
2017 LY_STMT_ANYXML, &notif->data, 0,
2018 LY_STMT_CHOICE, &notif->data, 0,
2019 LY_STMT_CONTAINER, &notif->data, 0,
2020 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2021 LY_STMT_GROUPING, &notif->groupings, 0,
2022 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2023 LY_STMT_LEAF, &notif->data, 0,
2024 LY_STMT_LEAF_LIST, &notif->data, 0,
2025 LY_STMT_LIST, &notif->data, 0,
2026 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2027 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2028 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2029 LY_STMT_TYPEDEF, &notif->typedefs, 0,
2030 LY_STMT_USES, &notif->data, 0,
2031 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002032 ));
2033
Michal Vaskob36053d2020-03-26 15:49:30 +01002034 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_NOTIFICATION, NULL, &notif->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002035 subelems_deallocator(16, subelems);
2036 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002037
2038 /* finalize parent pointers to the reallocated items */
2039 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2040
2041 return LY_SUCCESS;
2042}
2043
2044/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002045 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002046 *
2047 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002048 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002049 *
2050 * @return LY_ERR values.
2051 */
2052static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002053yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002054{
2055 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002056 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002057 LY_ERR ret = LY_SUCCESS;
2058 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002059
2060 /* create new grouping */
Michal Vaskob36053d2020-03-26 15:49:30 +01002061 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002062 grp->nodetype = LYS_GROUPING;
2063 grp->parent = gr_meta->parent;
2064
2065 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002066 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2067 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 +02002068
2069 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002070 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002071 LY_STMT_ACTION, &grp->actions, 0,
2072 LY_STMT_ANYDATA, &grp->data, 0,
2073 LY_STMT_ANYXML, &grp->data, 0,
2074 LY_STMT_CHOICE, &grp->data, 0,
2075 LY_STMT_CONTAINER, &grp->data, 0,
2076 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2077 LY_STMT_GROUPING, &grp->groupings, 0,
2078 LY_STMT_LEAF, &grp->data, 0,
2079 LY_STMT_LEAF_LIST, &grp->data, 0,
2080 LY_STMT_LIST, &grp->data, 0,
2081 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2082 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2083 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2084 LY_STMT_TYPEDEF, &grp->typedefs, 0,
2085 LY_STMT_USES, &grp->data, 0,
2086 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002087 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002088 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_GROUPING, NULL, &grp->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002089 subelems_deallocator(16, subelems);
2090 LY_CHECK_RET(ret);
2091
David Sedláke3ce9ef2019-07-23 16:34:30 +02002092 /* finalize parent pointers to the reallocated items */
2093 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2094
2095 return LY_SUCCESS;
2096}
2097
2098/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002099 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002100 *
2101 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002102 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002103 *
2104 * @return LY_ERR values.
2105 */
2106static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002107yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002108{
David Sedlákf111bcb2019-07-23 17:15:51 +02002109 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002110 LY_ERR ret = LY_SUCCESS;
2111 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002112
2113 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002114 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002115 cont->nodetype = LYS_CONTAINER;
2116 cont->parent = node_meta->parent;
2117
David Sedlákf111bcb2019-07-23 17:15:51 +02002118 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002119 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2120 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 +02002121
2122 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002123 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002124 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2125 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2126 LY_STMT_ANYXML, &cont->child, 0,
2127 LY_STMT_CHOICE, &cont->child, 0,
2128 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2129 LY_STMT_CONTAINER, &cont->child, 0,
2130 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2131 LY_STMT_GROUPING, &cont->groupings, 0,
2132 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2133 LY_STMT_LEAF, &cont->child, 0,
2134 LY_STMT_LEAF_LIST, &cont->child, 0,
2135 LY_STMT_LIST, &cont->child, 0,
2136 LY_STMT_MUST, &cont->musts, 0,
2137 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2138 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2139 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2140 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2141 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2142 LY_STMT_USES, &cont->child, 0,
2143 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2144 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002145 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002146 ret = yin_parse_content(ctx, subelems, 21, LY_STMT_CONTAINER, NULL, &cont->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002147 subelems_deallocator(21, subelems);
2148 LY_CHECK_RET(ret);
2149
David Sedlákf111bcb2019-07-23 17:15:51 +02002150 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2151
2152 return LY_SUCCESS;
2153}
2154
2155/**
David Sedlák5379d392019-07-24 10:42:03 +02002156 * @brief Parse case element.
2157 *
2158 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002159 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002160 *
2161 * @return LY_ERR values.
2162 */
2163static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002164yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002165{
David Sedlák5379d392019-07-24 10:42:03 +02002166 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002167 LY_ERR ret = LY_SUCCESS;
2168 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002169
2170 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002171 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002172 cas->nodetype = LYS_CASE;
2173 cas->parent = node_meta->parent;
2174
David Sedlák5379d392019-07-24 10:42:03 +02002175 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002176 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2177 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 +02002178
2179 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002180 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002181 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2182 LY_STMT_ANYXML, &cas->child, 0,
2183 LY_STMT_CHOICE, &cas->child, 0,
2184 LY_STMT_CONTAINER, &cas->child, 0,
2185 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2186 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2187 LY_STMT_LEAF, &cas->child, 0,
2188 LY_STMT_LEAF_LIST, &cas->child, 0,
2189 LY_STMT_LIST, &cas->child, 0,
2190 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2191 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2192 LY_STMT_USES, &cas->child, 0,
2193 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2194 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002195 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002196 ret = yin_parse_content(ctx, subelems, 14, LY_STMT_CASE, NULL, &cas->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002197 subelems_deallocator(14, subelems);
2198
2199 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002200}
2201
2202/**
David Sedlák05404f62019-07-24 14:11:53 +02002203 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002204 *
2205 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002206 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002207 *
2208 * @return LY_ERR values.
2209 */
2210LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002211yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002212{
David Sedlák81497a32019-08-13 16:56:26 +02002213 LY_ERR ret = LY_SUCCESS;
2214 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002215 struct lysp_node_choice *choice;
2216
2217 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002218 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002219
David Sedlákb7abcfa2019-07-24 12:33:35 +02002220 choice->nodetype = LYS_CHOICE;
2221 choice->parent = node_meta->parent;
2222
David Sedlákb7abcfa2019-07-24 12:33:35 +02002223 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002224 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2225 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 +02002226
2227 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002228 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002229 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2230 LY_STMT_ANYXML, &choice->child, 0,
2231 LY_STMT_CASE, &choice->child, 0,
2232 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2233 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2234 LY_STMT_CONTAINER, &choice->child, 0,
2235 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2236 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2237 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2238 LY_STMT_LEAF, &choice->child, 0,
2239 LY_STMT_LEAF_LIST, &choice->child, 0,
2240 LY_STMT_LIST, &choice->child, 0,
2241 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2242 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2243 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2244 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2245 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002246 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002247 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_CHOICE, NULL, &choice->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002248 subelems_deallocator(17, subelems);
2249 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002250}
2251
2252/**
David Sedlák05404f62019-07-24 14:11:53 +02002253 * @brief Parse input or output element.
2254 *
2255 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002256 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002257 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2258 *
2259 * @return LY_ERR values.
2260 */
2261static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002262yin_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 +02002263{
David Sedlák81497a32019-08-13 16:56:26 +02002264 LY_ERR ret = LY_SUCCESS;
2265 struct yin_subelement *subelems = NULL;
2266
David Sedlák05404f62019-07-24 14:11:53 +02002267 /* initiate structure */
Radek Krejcid6b76452019-09-03 17:03:03 +02002268 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002269 inout_meta->inout_p->parent = inout_meta->parent;
2270
2271 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002272 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2273 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 +02002274
2275 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002276 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002277 LY_STMT_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2278 LY_STMT_ANYXML, &inout_meta->inout_p->data, 0,
2279 LY_STMT_CHOICE, &inout_meta->inout_p->data, 0,
2280 LY_STMT_CONTAINER, &inout_meta->inout_p->data, 0,
2281 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2282 LY_STMT_LEAF, &inout_meta->inout_p->data, 0,
2283 LY_STMT_LEAF_LIST, &inout_meta->inout_p->data, 0,
2284 LY_STMT_LIST, &inout_meta->inout_p->data, 0,
2285 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2286 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2287 LY_STMT_USES, &inout_meta->inout_p->data, 0,
2288 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002289 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002290 ret = yin_parse_content(ctx, subelems, 12, inout_kw, NULL, &inout_meta->inout_p->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002291 subelems_deallocator(12, subelems);
2292 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002293
Michal Vaskob83af8a2020-01-06 09:49:22 +01002294 if (!inout_meta->inout_p->data) {
2295 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2296 return LY_EVALID;
2297 }
2298
David Sedlák05404f62019-07-24 14:11:53 +02002299 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002300 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 +02002301
2302 return LY_SUCCESS;
2303}
2304
David Sedlák992fb7c2019-07-24 16:51:01 +02002305/**
2306 * @brief Parse action element.
2307 *
2308 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002309 * @param[in] act_meta Meta information about parent node and actions to add to.
2310 *
2311 * @return LY_ERR values.
2312 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002313static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002314yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002315{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002316 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002317 LY_ERR ret = LY_SUCCESS;
2318 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002319
2320 /* create new action */
Michal Vaskob36053d2020-03-26 15:49:30 +01002321 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *acts, act, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002322 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002323 act->parent = act_meta->parent;
2324
2325 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002326 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2327 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 +02002328
2329 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002330 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002331 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2332 LY_STMT_GROUPING, &act->groupings, 0,
2333 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2334 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2335 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2336 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2337 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2338 LY_STMT_TYPEDEF, &act->typedefs, 0,
2339 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002340 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002341 ret = (yin_parse_content(ctx, subelems, 9, LY_STMT_ACTION, NULL, &act->exts));
David Sedlák81497a32019-08-13 16:56:26 +02002342 subelems_deallocator(9, subelems);
2343 LY_CHECK_RET(ret);
2344
David Sedlák85d0eca2019-07-24 15:15:21 +02002345 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2346
2347 return LY_SUCCESS;
2348}
2349
David Sedlák05404f62019-07-24 14:11:53 +02002350/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002351 * @brief Parse augment element.
2352 *
2353 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002354 * @param[in] aug_meta Meta information about parent node and augments to add to.
2355 *
2356 * @return LY_ERR values.
2357 */
2358static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002359yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002360{
2361 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002362 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002363 LY_ERR ret = LY_SUCCESS;
2364 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002365
2366 /* create new augment */
Michal Vaskob36053d2020-03-26 15:49:30 +01002367 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002368 aug->nodetype = LYS_AUGMENT;
2369 aug->parent = aug_meta->parent;
2370
2371 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002372 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2373 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2374 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002375
2376 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002377 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002378 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2379 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2380 LY_STMT_ANYXML, &aug->child, 0,
2381 LY_STMT_CASE, &aug->child, 0,
2382 LY_STMT_CHOICE, &aug->child, 0,
2383 LY_STMT_CONTAINER, &aug->child, 0,
2384 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2385 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
2386 LY_STMT_LEAF, &aug->child, 0,
2387 LY_STMT_LEAF_LIST, &aug->child, 0,
2388 LY_STMT_LIST, &aug->child, 0,
2389 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2390 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2391 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2392 LY_STMT_USES, &aug->child, 0,
2393 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2394 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002395 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002396 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_AUGMENT, NULL, &aug->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002397 subelems_deallocator(17, subelems);
2398 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002399
2400 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2401
2402 return LY_SUCCESS;
2403}
2404
David Sedlák8b754462019-07-25 16:22:13 +02002405/**
2406 * @brief Parse deviate element.
2407 *
2408 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002409 * @param[in] deviates Deviates to add to.
2410 *
2411 * @return LY_ERR values.
2412 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002413static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002414yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002415{
2416 LY_ERR ret = LY_SUCCESS;
2417 uint8_t dev_mod;
2418 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002419 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002420 struct lysp_deviate_add *d_add = NULL;
2421 struct lysp_deviate_rpl *d_rpl = NULL;
2422 struct lysp_deviate_del *d_del = NULL;
2423
2424 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002425 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2426 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 +02002427
2428 if (strcmp(temp_val, "not-supported") == 0) {
2429 dev_mod = LYS_DEV_NOT_SUPPORTED;
2430 } else if (strcmp(temp_val, "add") == 0) {
2431 dev_mod = LYS_DEV_ADD;
2432 } else if (strcmp(temp_val, "replace") == 0) {
2433 dev_mod = LYS_DEV_REPLACE;
2434 } else if (strcmp(temp_val, "delete") == 0) {
2435 dev_mod = LYS_DEV_DELETE;
2436 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002437 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
2438 "not-supported", "add", "replace", "delete");
Michal Vaskob36053d2020-03-26 15:49:30 +01002439 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002440 return LY_EVALID;
2441 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002442 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002443
2444 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2445 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002446 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002447 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002448 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák4ffcec82019-07-25 15:10:21 +02002449 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002450 ret = yin_parse_content(ctx, subelems, 1, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002451
2452 } else if (dev_mod == LYS_DEV_ADD) {
2453 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002454 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002455 d = (struct lysp_deviate *)d_add;
2456 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2457 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2458 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002459 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2460 {LY_STMT_DEFAULT, &d_add->dflts, 0},
2461 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2462 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2463 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2464 {LY_STMT_MUST, &d_add->musts, 0},
2465 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2466 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2467 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002468 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002469 ret = yin_parse_content(ctx, subelems, 9, LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002470
2471 } else if (dev_mod == LYS_DEV_REPLACE) {
2472 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002473 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002474 d = (struct lysp_deviate *)d_rpl;
2475 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2476 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2477 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002478 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2479 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2480 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2481 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2482 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2483 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2484 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2485 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002486 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002487 ret = yin_parse_content(ctx, subelems, 8, LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002488
2489 } else {
2490 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002491 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002492 d = (struct lysp_deviate *)d_del;
2493 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002494 {LY_STMT_DEFAULT, &d_del->dflts, 0},
2495 {LY_STMT_MUST, &d_del->musts, 0},
2496 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2497 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2498 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002499 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002500 ret = yin_parse_content(ctx, subelems, 5, LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002501 }
2502 LY_CHECK_GOTO(ret, cleanup);
2503
2504 d->mod = dev_mod;
2505 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002506 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002507
2508 return ret;
2509
2510cleanup:
2511 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002512 return ret;
2513}
2514
David Sedlák992fb7c2019-07-24 16:51:01 +02002515/**
David Sedlák8b754462019-07-25 16:22:13 +02002516 * @brief Parse deviation element.
2517 *
2518 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002519 * @param[in] deviations Deviations to add to.
2520 *
2521 * @return LY_ERR values.
2522 */
2523static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002524yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002525{
2526 struct lysp_deviation *dev;
2527
2528 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002529 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002530
2531 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002532 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2533 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2534 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
David Sedlák8b754462019-07-25 16:22:13 +02002535 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002536 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2537 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2538 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2539 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8b754462019-07-25 16:22:13 +02002540 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002541 return yin_parse_content(ctx, subelems, 4, LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002542}
2543
2544/**
David Sedlákb4e44562019-07-04 15:42:12 +02002545 * @brief Map keyword type to substatement info.
2546 *
2547 * @param[in] kw Keyword type.
2548 *
2549 * @return correct LYEXT_SUBSTMT information.
2550 */
2551static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002552kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002553{
2554 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002555 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002556 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002557 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002558 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002559 case LY_STMT_BELONGS_TO:
David Sedlákb4e44562019-07-04 15:42:12 +02002560 return LYEXT_SUBSTMT_BELONGSTO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002561 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002562 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002563 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002564 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002565 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002566 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002567 case LY_STMT_ERROR_APP_TAG:
David Sedlákb4e44562019-07-04 15:42:12 +02002568 return LYEXT_SUBSTMT_ERRTAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002569 case LY_STMT_ERROR_MESSAGE:
David Sedlákb4e44562019-07-04 15:42:12 +02002570 return LYEXT_SUBSTMT_ERRMSG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002571 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002572 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002573 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002574 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002575 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002576 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002577 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002578 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002579 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002580 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002581 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002582 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002583 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002584 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002585 case LY_STMT_REVISION_DATE:
David Sedlákb4e44562019-07-04 15:42:12 +02002586 return LYEXT_SUBSTMT_REVISIONDATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002587 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002588 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002589 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002590 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002591 case LY_STMT_YANG_VERSION:
David Sedlákb4e44562019-07-04 15:42:12 +02002592 return LYEXT_SUBSTMT_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002593 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002594 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002595 case LY_STMT_REQUIRE_INSTANCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002596 return LYEXT_SUBSTMT_REQINSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002597 case LY_STMT_YIN_ELEMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002598 return LYEXT_SUBSTMT_YINELEM;
Radek Krejcid6b76452019-09-03 17:03:03 +02002599 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002600 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002601 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002602 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002603 case LY_STMT_ORDERED_BY:
David Sedlákb4e44562019-07-04 15:42:12 +02002604 return LYEXT_SUBSTMT_ORDEREDBY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002605 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002606 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002607 case LY_STMT_FRACTION_DIGITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002608 return LYEXT_SUBSTMT_FRACDIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002609 case LY_STMT_MAX_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002610 return LYEXT_SUBSTMT_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002611 case LY_STMT_MIN_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002612 return LYEXT_SUBSTMT_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02002613 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002614 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002615 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002616 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002617 case LY_STMT_IF_FEATURE:
David Sedlákb4e44562019-07-04 15:42:12 +02002618 return LYEXT_SUBSTMT_IFFEATURE;
2619 default:
2620 return LYEXT_SUBSTMT_SELF;
2621 }
2622}
2623
David Sedlákc5b20842019-08-13 10:18:31 +02002624/**
2625 * @brief map keyword to keyword-group.
2626 *
2627 * @param[in] ctx YIN parser context used for logging.
2628 * @param[in] kw Keyword that is child of module or submodule.
2629 * @param[out] group Group of keyword.
2630 *
2631 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2632 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002633static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002634kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002635{
2636 switch (kw) {
2637 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02002638 case LY_STMT_NONE:
2639 case LY_STMT_NAMESPACE:
2640 case LY_STMT_PREFIX:
2641 case LY_STMT_BELONGS_TO:
2642 case LY_STMT_YANG_VERSION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002643 *group = Y_MOD_MODULE_HEADER;
2644 break;
2645 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02002646 case LY_STMT_INCLUDE:
2647 case LY_STMT_IMPORT:
David Sedláke6cd89e2019-08-07 12:46:02 +02002648 *group = Y_MOD_LINKAGE;
2649 break;
2650 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02002651 case LY_STMT_ORGANIZATION:
2652 case LY_STMT_CONTACT:
2653 case LY_STMT_DESCRIPTION:
2654 case LY_STMT_REFERENCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002655 *group = Y_MOD_META;
2656 break;
2657 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02002658 case LY_STMT_REVISION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002659 *group = Y_MOD_REVISION;
2660 break;
2661 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02002662 case LY_STMT_ANYDATA:
2663 case LY_STMT_ANYXML:
2664 case LY_STMT_AUGMENT:
2665 case LY_STMT_CHOICE:
2666 case LY_STMT_CONTAINER:
2667 case LY_STMT_DEVIATION:
2668 case LY_STMT_EXTENSION:
2669 case LY_STMT_FEATURE:
2670 case LY_STMT_GROUPING:
2671 case LY_STMT_IDENTITY:
2672 case LY_STMT_LEAF:
2673 case LY_STMT_LEAF_LIST:
2674 case LY_STMT_LIST:
2675 case LY_STMT_NOTIFICATION:
2676 case LY_STMT_RPC:
2677 case LY_STMT_TYPEDEF:
2678 case LY_STMT_USES:
2679 case LY_STMT_EXTENSION_INSTANCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002680 *group = Y_MOD_BODY;
2681 break;
2682 default:
Michal Vaskob36053d2020-03-26 15:49:30 +01002683 LOGINT(ctx->xmlctx->ctx);
David Sedláke6cd89e2019-08-07 12:46:02 +02002684 return LY_EINT;
2685 }
2686
2687 return LY_SUCCESS;
2688}
2689
David Sedlákc5b20842019-08-13 10:18:31 +02002690/**
2691 * @brief Check if relative order of two keywords is valid.
2692 *
2693 * @param[in] ctx YIN parser context used for logging.
2694 * @param[in] kw Current keyword.
2695 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002696 * @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 +02002697 * because relative order is required only in module and submodule sub-elements, used for logging.
2698 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002699 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002700 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002701static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002702yin_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 +02002703{
Radek Krejcid6b76452019-09-03 17:03:03 +02002704 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002705 enum yang_module_stmt gr, next_gr;
2706
2707 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2708 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2709
2710 if (gr > next_gr) {
2711 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2712 return LY_EVALID;
2713 }
2714
2715 return LY_SUCCESS;
2716}
2717
David Sedlákc5dd0942019-09-13 10:23:59 +02002718/**
2719 * @brief Get element name prefixed by full URI of xml namespace.
2720 *
2721 * @param[in] ctx YIN parser context used for logging and to get inormation about xml namespaces.
2722 * @param[in] name Name of element.
2723 * @param[in] name_len Length of element name.
2724 * @param[in] prefix Prefix of element.
2725 * @param[in] prefix_len Length of element prefix.
2726 *
2727 * @return Element name prefixed by URI on success, NULL on failure.
2728 */
2729static const char *
Michal Vaskob36053d2020-03-26 15:49:30 +01002730name2nsname(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 +02002731{
Michal Vaskob36053d2020-03-26 15:49:30 +01002732 const struct lyxml_ns *ns = lyxml_ns_get(ctx->xmlctx, prefix, prefix_len);
2733 LY_CHECK_ERR_RET(!ns, LOGINT(ctx->xmlctx->ctx), NULL);
David Sedlák068dd352019-09-13 09:08:22 +02002734
Radek Krejci02728562019-09-18 14:13:05 +02002735 if (!strcmp(ns->uri, YIN_NS_URI)) {
2736 /* standard YANG statement in YIN namespace - keep it unprefixed as in case of YANG */
Michal Vaskob36053d2020-03-26 15:49:30 +01002737 return lydict_insert(ctx->xmlctx->ctx, name, name_len);
Radek Krejci02728562019-09-18 14:13:05 +02002738 }
2739 /* some statement in special namespace (extension instance) */
David Sedláke0ef1c62019-09-13 10:05:55 +02002740 size_t ns_len = strlen(ns->uri);
2741 size_t len = ns_len + name_len + 1; /* +1 because of ':' delimiter between ns and actual name */
2742
2743 char *result;
2744 char *temp;
2745 temp = result = malloc(sizeof(*temp) * (len + 1)); /* +1 for '\0' terminator */
Michal Vaskob36053d2020-03-26 15:49:30 +01002746 LY_CHECK_ERR_RET(!temp, LOGMEM(ctx->xmlctx->ctx), NULL);
David Sedláke0ef1c62019-09-13 10:05:55 +02002747
2748 strcpy(result, ns->uri);
2749 result[ns_len] = ':';
2750 temp = &result[ns_len + 1];
2751 strncpy(temp, name, name_len);
2752 result[len] = '\0';
2753
Michal Vaskob36053d2020-03-26 15:49:30 +01002754 return lydict_insert_zc(ctx->xmlctx->ctx, result);
David Sedlák068dd352019-09-13 09:08:22 +02002755}
2756
David Sedlákd6e56892019-07-01 15:40:24 +02002757LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002758yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
2759 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02002760{
2761 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01002762 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02002763 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002764 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002765
Michal Vaskob36053d2020-03-26 15:49:30 +01002766 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02002767
Michal Vaskob36053d2020-03-26 15:49:30 +01002768 if (ctx->xmlctx->ws_only) {
2769 /* check whether there are any children */
2770 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
2771 } else {
2772 /* we want to parse the value */
2773 next_status = LYXML_ELEM_CLOSE;
2774 }
2775
2776 if (next_status == LYXML_ELEMENT) {
2777 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
2778
2779 /* current element has subelements as content */
2780 while (ctx->xmlctx->status == LYXML_ELEMENT) {
2781 /* match keyword */
2782 last_kw = kw;
2783 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
2784 ctx->xmlctx->prefix_len, current_element);
2785
2786 /* check if this element can be child of current element */
2787 subelem = get_record(kw, subelem_info_size, subelem_info);
2788 if (!subelem) {
2789 if (current_element == LY_STMT_DEVIATE && isdevsub(kw)) {
2790 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2791 } else {
2792 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
2793 ctx->xmlctx->name, ly_stmt2str(current_element));
2794 }
2795 ret = LY_EVALID;
2796 goto cleanup;
2797 }
2798
2799 /* relative order is required only in module and submodule sub-elements */
2800 if (current_element == LY_STMT_MODULE || current_element == LY_STMT_SUBMODULE) {
2801 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2802 LY_CHECK_GOTO(ret, cleanup);
2803 }
2804
2805 /* flag check */
2806 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
2807 /* subelement uniquenes */
2808 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
2809 return LY_EVALID;
2810 }
2811 if (subelem->flags & YIN_SUBELEM_FIRST) {
2812 /* subelement is supposed to be defined as first subelement */
2813 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
2814 LY_CHECK_GOTO(ret, cleanup);
2815 }
2816 if (subelem->flags & YIN_SUBELEM_VER2) {
2817 /* subelement is supported only in version 1.1 or higher */
2818 if (ctx->mod_version < 2) {
2819 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 +02002820 ret = LY_EVALID;
2821 goto cleanup;
2822 }
David Sedlákd6e56892019-07-01 15:40:24 +02002823 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002824 /* note that element was parsed for easy uniqueness check in next iterations */
2825 subelem->flags |= YIN_SUBELEM_PARSED;
2826
2827 switch (kw) {
2828 /* call responsible function */
2829 case LY_STMT_EXTENSION_INSTANCE:
2830 ret = yin_parse_extension_instance(ctx, kw2lyext_substmt(current_element),
Radek Krejci7eb54ba2020-05-18 16:30:04 +02002831 (subelem->dest) ? *((LY_ARRAY_SIZE_TYPE*)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01002832 break;
2833 case LY_STMT_ACTION:
2834 case LY_STMT_RPC:
2835 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
2836 break;
2837 case LY_STMT_ANYDATA:
2838 case LY_STMT_ANYXML:
2839 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
2840 break;
2841 case LY_STMT_ARGUMENT:
2842 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
2843 break;
2844 case LY_STMT_AUGMENT:
2845 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
2846 break;
2847 case LY_STMT_BASE:
2848 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
2849 break;
2850 case LY_STMT_BELONGS_TO:
2851 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
2852 break;
2853 case LY_STMT_BIT:
2854 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
2855 break;
2856 case LY_STMT_CASE:
2857 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
2858 break;
2859 case LY_STMT_CHOICE:
2860 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
2861 break;
2862 case LY_STMT_CONFIG:
2863 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
2864 break;
2865 case LY_STMT_CONTACT:
2866 case LY_STMT_DESCRIPTION:
2867 case LY_STMT_ORGANIZATION:
2868 case LY_STMT_REFERENCE:
2869 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
2870 break;
2871 case LY_STMT_CONTAINER:
2872 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
2873 break;
2874 case LY_STMT_DEFAULT:
2875 case LY_STMT_ERROR_APP_TAG:
2876 case LY_STMT_KEY:
2877 case LY_STMT_PRESENCE:
2878 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
2879 break;
2880 case LY_STMT_DEVIATE:
2881 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
2882 break;
2883 case LY_STMT_DEVIATION:
2884 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
2885 break;
2886 case LY_STMT_ENUM:
2887 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
2888 break;
2889 case LY_STMT_ERROR_MESSAGE:
2890 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
2891 break;
2892 case LY_STMT_EXTENSION:
2893 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
2894 break;
2895 case LY_STMT_FEATURE:
2896 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
2897 break;
2898 case LY_STMT_FRACTION_DIGITS:
2899 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
2900 break;
2901 case LY_STMT_GROUPING:
2902 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
2903 break;
2904 case LY_STMT_IDENTITY:
2905 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
2906 break;
2907 case LY_STMT_IF_FEATURE:
2908 case LY_STMT_UNITS:
2909 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
2910 break;
2911 case LY_STMT_IMPORT:
2912 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
2913 break;
2914 case LY_STMT_INCLUDE:
2915 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
2916 break;
2917 case LY_STMT_INPUT:
2918 case LY_STMT_OUTPUT:
2919 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
2920 break;
2921 case LY_STMT_LEAF:
2922 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
2923 break;
2924 case LY_STMT_LEAF_LIST:
2925 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
2926 break;
2927 case LY_STMT_LENGTH:
2928 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
2929 break;
2930 case LY_STMT_LIST:
2931 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
2932 break;
2933 case LY_STMT_MANDATORY:
2934 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
2935 break;
2936 case LY_STMT_MAX_ELEMENTS:
2937 case LY_STMT_MIN_ELEMENTS:
2938 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
2939 break;
2940 case LY_STMT_MODIFIER:
2941 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
2942 break;
2943 case LY_STMT_MUST:
2944 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
2945 break;
2946 case LY_STMT_NAMESPACE:
2947 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
2948 break;
2949 case LY_STMT_NOTIFICATION:
2950 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
2951 break;
2952 case LY_STMT_ORDERED_BY:
2953 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
2954 break;
2955 case LY_STMT_PATH:
2956 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
2957 break;
2958 case LY_STMT_PATTERN:
2959 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
2960 break;
2961 case LY_STMT_VALUE:
2962 case LY_STMT_POSITION:
2963 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
2964 break;
2965 case LY_STMT_PREFIX:
2966 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
2967 break;
2968 case LY_STMT_RANGE:
2969 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
2970 break;
2971 case LY_STMT_REFINE:
2972 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
2973 break;
2974 case LY_STMT_REQUIRE_INSTANCE:
2975 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
2976 break;
2977 case LY_STMT_REVISION:
2978 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
2979 break;
2980 case LY_STMT_REVISION_DATE:
2981 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
2982 break;
2983 case LY_STMT_STATUS:
2984 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
2985 break;
2986 case LY_STMT_TYPE:
2987 ret = yin_parse_type(ctx, current_element, subelem);
2988 break;
2989 case LY_STMT_TYPEDEF:
2990 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
2991 break;
2992 case LY_STMT_UNIQUE:
2993 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
2994 break;
2995 case LY_STMT_USES:
2996 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
2997 break;
2998 case LY_STMT_WHEN:
2999 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3000 break;
3001 case LY_STMT_YANG_VERSION:
3002 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3003 break;
3004 case LY_STMT_YIN_ELEMENT:
3005 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3006 break;
3007 case LY_STMT_ARG_TEXT:
3008 case LY_STMT_ARG_VALUE:
3009 /* TODO what to do with content/attributes? */
3010 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3011 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3012 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3013 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3014 }
3015 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3016 break;
3017 default:
3018 LOGINT(ctx->xmlctx->ctx);
3019 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003020 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003021 LY_CHECK_GOTO(ret, cleanup);
3022 subelem = NULL;
3023
3024 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003025 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003026 } else {
3027 LY_CHECK_RET(ret);
3028 /* elements with text or none content */
3029 /* save text content, if text_content isn't set, it's just ignored */
3030 /* no resources are allocated in this branch, no need to use cleanup label */
3031 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3032 if (text_content) {
3033 *text_content = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3034 LY_CHECK_RET(!*text_content, LY_EMEM);
3035 }
3036
3037 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003038 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003039
David Sedlák8b754462019-07-25 16:22:13 +02003040 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3041 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003042
3043cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003044 return ret;
3045}
3046
David Sedlák619db942019-07-03 14:47:30 +02003047LY_ERR
Radek Krejci7eb54ba2020-05-18 16:30:04 +02003048yin_parse_extension_instance(struct lys_yin_parser_ctx *ctx, LYEXT_SUBSTMT subelem, LY_ARRAY_SIZE_TYPE subelem_index,
Michal Vaskob36053d2020-03-26 15:49:30 +01003049 struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003050{
David Sedlák1e2cdd02019-06-27 14:17:43 +02003051 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003052 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003053
Michal Vaskob36053d2020-03-26 15:49:30 +01003054 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3055
3056 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003057
3058 e->yin = 0;
3059 /* store name and insubstmt info */
Michal Vaskob36053d2020-03-26 15:49:30 +01003060 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 +02003061 LY_CHECK_RET(!e->name, LY_EMEM);
David Sedlák619db942019-07-03 14:47:30 +02003062 e->insubstmt = subelem;
3063 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003064 e->yin |= LYS_YIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01003065 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003066
David Sedlákb1a78352019-06-28 16:16:29 +02003067 /* store attributes as subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003068 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3069 if (!ctx->xmlctx->prefix) {
David Sedlákb1a78352019-06-28 16:16:29 +02003070 new_subelem = calloc(1, sizeof(*new_subelem));
3071 if (!e->child) {
3072 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003073 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003074 last_subelem->next = new_subelem;
3075 }
3076 last_subelem = new_subelem;
3077
3078 last_subelem->flags |= LYS_YIN_ATTR;
Michal Vaskob36053d2020-03-26 15:49:30 +01003079 last_subelem->stmt = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák169cc522019-08-15 13:23:45 +02003080 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003081 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák169cc522019-08-15 13:23:45 +02003082
Michal Vaskob36053d2020-03-26 15:49:30 +01003083 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 +02003084 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003085 } else {
3086 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003087 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003088
3089 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003090 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003091
David Sedlákf250ecf2019-07-01 11:02:05 +02003092 /* parse subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003093 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3094 if (ctx->xmlctx->ws_only) {
3095 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3096 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3097 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3098 if (!e->child) {
3099 e->child = new_subelem;
3100 } else {
3101 last_subelem->next = new_subelem;
David Sedlákb1a78352019-06-28 16:16:29 +02003102 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003103 last_subelem = new_subelem;
David Sedlák169cc522019-08-15 13:23:45 +02003104
Michal Vaskob36053d2020-03-26 15:49:30 +01003105 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3106 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003107 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003108 } else if (ctx->xmlctx->value_len) {
3109 /* save text content */
3110 e->argument = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3111 LY_CHECK_RET(!e->argument, LY_EMEM);
3112
3113 /* parser next */
3114 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003115 }
3116
3117 return LY_SUCCESS;
3118}
3119
David Sedlákaa98bba2019-09-12 11:52:14 +02003120/**
3121 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
3122 *
3123 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákaa98bba2019-09-12 11:52:14 +02003124 * @param[in] elem_type Type of element that is currently being parsed.
3125 * @param[out] arg Value to write to.
3126 *
3127 * @return LY_ERR values.
3128 */
3129static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003130yin_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 +02003131{
David Sedlák071f7662019-09-12 02:02:51 +02003132 enum ly_stmt child;
David Sedláke6284fc2019-09-10 11:57:02 +02003133
Michal Vaskob36053d2020-03-26 15:49:30 +01003134 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3135
David Sedláke6284fc2019-09-10 11:57:02 +02003136 switch (elem_type) {
3137 case LY_STMT_ACTION:
3138 case LY_STMT_ANYDATA:
3139 case LY_STMT_ANYXML:
3140 case LY_STMT_ARGUMENT:
3141 case LY_STMT_BASE:
3142 case LY_STMT_BIT:
3143 case LY_STMT_CASE:
3144 case LY_STMT_CHOICE:
3145 case LY_STMT_CONTAINER:
3146 case LY_STMT_ENUM:
3147 case LY_STMT_EXTENSION:
3148 case LY_STMT_FEATURE:
3149 case LY_STMT_GROUPING:
3150 case LY_STMT_IDENTITY:
3151 case LY_STMT_IF_FEATURE:
3152 case LY_STMT_LEAF:
3153 case LY_STMT_LEAF_LIST:
3154 case LY_STMT_LIST:
3155 case LY_STMT_MODULE:
3156 case LY_STMT_NOTIFICATION:
3157 case LY_STMT_RPC:
3158 case LY_STMT_SUBMODULE:
3159 case LY_STMT_TYPE:
3160 case LY_STMT_TYPEDEF:
3161 case LY_STMT_UNITS:
3162 case LY_STMT_USES:
Michal Vaskob36053d2020-03-26 15:49:30 +01003163 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 +02003164 break;
3165 case LY_STMT_AUGMENT:
3166 case LY_STMT_DEVIATION:
3167 case LY_STMT_REFINE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003168 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 +02003169 break;
3170 case LY_STMT_CONFIG:
3171 case LY_STMT_DEFAULT:
3172 case LY_STMT_DEVIATE:
3173 case LY_STMT_ERROR_APP_TAG:
David Sedláke6284fc2019-09-10 11:57:02 +02003174 case LY_STMT_FRACTION_DIGITS:
3175 case LY_STMT_KEY:
3176 case LY_STMT_LENGTH:
3177 case LY_STMT_MANDATORY:
3178 case LY_STMT_MAX_ELEMENTS:
3179 case LY_STMT_MIN_ELEMENTS:
3180 case LY_STMT_MODIFIER:
3181 case LY_STMT_ORDERED_BY:
3182 case LY_STMT_PATH:
3183 case LY_STMT_PATTERN:
3184 case LY_STMT_POSITION:
3185 case LY_STMT_PREFIX:
3186 case LY_STMT_PRESENCE:
3187 case LY_STMT_RANGE:
3188 case LY_STMT_REQUIRE_INSTANCE:
3189 case LY_STMT_STATUS:
3190 case LY_STMT_VALUE:
3191 case LY_STMT_YANG_VERSION:
3192 case LY_STMT_YIN_ELEMENT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003193 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 +02003194 break;
3195 case LY_STMT_IMPORT:
3196 case LY_STMT_INCLUDE:
3197 case LY_STMT_BELONGS_TO:
Michal Vaskob36053d2020-03-26 15:49:30 +01003198 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 +02003199 break;
3200 case LY_STMT_INPUT:
3201 case LY_STMT_OUTPUT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003202 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 +02003203 break;
3204 case LY_STMT_MUST:
3205 case LY_STMT_WHEN:
Michal Vaskob36053d2020-03-26 15:49:30 +01003206 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 +02003207 break;
3208 case LY_STMT_NAMESPACE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003209 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 +02003210 break;
3211 case LY_STMT_REVISION:
3212 case LY_STMT_REVISION_DATE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003213 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 +02003214 break;
3215 case LY_STMT_UNIQUE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003216 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 +02003217 break;
David Sedlák071f7662019-09-12 02:02:51 +02003218 /* argument is mapped to yin element */
3219 case LY_STMT_CONTACT:
3220 case LY_STMT_DESCRIPTION:
3221 case LY_STMT_ORGANIZATION:
3222 case LY_STMT_REFERENCE:
3223 case LY_STMT_ERROR_MESSAGE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003224 /* there shouldn't be any attribute, argument is supposed to be first subelement */
Michal Vaskob36053d2020-03-26 15:49:30 +01003225 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3226
3227 /* no content */
3228 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3229 if (ctx->xmlctx->ws_only) {
3230 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3231 }
3232 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3233 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
3234 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
David Sedlák071f7662019-09-12 02:02:51 +02003235 return LY_EVALID;
3236 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003237
3238 /* parse child element */
3239 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
3240 if ((elem_type == LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_VALUE) ||
3241 (elem_type != LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_TEXT)) {
3242 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3243 ly_stmt2str(elem_type));
3244 return LY_EVALID;
David Sedlákaa98bba2019-09-12 11:52:14 +02003245 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003246 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3247
3248 /* no attributes expected? TODO */
3249 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3250 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3251 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3252 }
3253
3254 /* load and save content */
3255 *arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3256 LY_CHECK_RET(!*arg, LY_EMEM);
3257
3258 /* load closing tag of subelement */
3259 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3260
3261 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3262 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3263 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3264 }*/
David Sedlákb0ca07d2019-09-11 11:54:05 +02003265 break;
David Sedláke6284fc2019-09-10 11:57:02 +02003266 default:
Michal Vaskob36053d2020-03-26 15:49:30 +01003267 LOGINT(ctx->xmlctx->ctx);
David Sedlák071f7662019-09-12 02:02:51 +02003268 return LY_EINT;
David Sedláke6284fc2019-09-10 11:57:02 +02003269 }
3270
David Sedlák071f7662019-09-12 02:02:51 +02003271 return LY_SUCCESS;
David Sedláke6284fc2019-09-10 11:57:02 +02003272}
3273
3274LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003275yin_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 +02003276{
3277 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003278 struct lysp_stmt *last = NULL, *new = NULL;
3279
Michal Vaskob36053d2020-03-26 15:49:30 +01003280 assert(ctx->xmlctx->status == LYXML_ELEMENT);
David Sedláke0ef1c62019-09-13 10:05:55 +02003281
3282 /* allocate new structure for element */
3283 *element = calloc(1, sizeof(**element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003284 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3285 (*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 +02003286 LY_CHECK_ERR_GOTO(!(*element)->stmt, ret = LY_EMEM, cleanup);
David Sedláke0ef1c62019-09-13 10:05:55 +02003287
Michal Vaskob36053d2020-03-26 15:49:30 +01003288 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3289 ctx->xmlctx->prefix_len, parent);
David Sedlákb1a78352019-06-28 16:16:29 +02003290
3291 last = (*element)->child;
David Sedláke6284fc2019-09-10 11:57:02 +02003292 if ((*element)->kw == LY_STMT_NONE) {
3293 /* unrecognized element */
Michal Vaskob36053d2020-03-26 15:49:30 +01003294 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3295 ly_stmt2str(parent));
David Sedlákaa98bba2019-09-12 11:52:14 +02003296 ret = LY_EVALID;
3297 goto cleanup;
David Sedláke6284fc2019-09-10 11:57:02 +02003298 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3299 /* element is known yang keyword, which means argument can be parsed correctly. */
Michal Vaskob36053d2020-03-26 15:49:30 +01003300 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
David Sedlákaa98bba2019-09-12 11:52:14 +02003301 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003302 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01003303 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3304
David Sedlákaa98bba2019-09-12 11:52:14 +02003305 /* load attributes in generic way, save all attributes in linked list */
Michal Vaskob36053d2020-03-26 15:49:30 +01003306 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedláke6284fc2019-09-10 11:57:02 +02003307 new = calloc(1, sizeof(*last));
Michal Vaskob36053d2020-03-26 15:49:30 +01003308 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003309 if (!(*element)->child) {
3310 /* save first */
3311 (*element)->child = new;
3312 } else {
3313 last->next = new;
3314 }
3315 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003316
David Sedláke6284fc2019-09-10 11:57:02 +02003317 last->flags |= LYS_YIN_ATTR;
Michal Vaskob36053d2020-03-26 15:49:30 +01003318 last->stmt = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlákb0ca07d2019-09-11 11:54:05 +02003319 last->kw = LY_STMT_NONE;
David Sedláke6284fc2019-09-10 11:57:02 +02003320 /* attributes with prefix are ignored */
Michal Vaskob36053d2020-03-26 15:49:30 +01003321 if (!ctx->xmlctx->prefix) {
3322 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3323
3324 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 +02003325 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003326 } else {
3327 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003328 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003329 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003330 }
3331 }
3332
Michal Vaskob36053d2020-03-26 15:49:30 +01003333 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3334 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3335 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3336 /* parse subelements */
3337 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
David Sedlákaa98bba2019-09-12 11:52:14 +02003338 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003339 if (!(*element)->child) {
3340 /* save first */
3341 (*element)->child = new;
3342 } else {
3343 last->next = new;
David Sedláka82ecff2019-08-16 10:51:48 +02003344 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003345 last = new;
David Sedlák169cc522019-08-15 13:23:45 +02003346
Michal Vaskob36053d2020-03-26 15:49:30 +01003347 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3348 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003349 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003350 } else {
3351 /* save element content */
3352 if (ctx->xmlctx->value_len) {
3353 (*element)->arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3354 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
3355 }
3356
3357 /* read closing tag */
3358 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003359 }
3360
David Sedlákb0ca07d2019-09-11 11:54:05 +02003361cleanup:
David Sedlákb0ca07d2019-09-11 11:54:05 +02003362 return ret;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003363}
3364
3365LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003366yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003367{
David Sedlák81497a32019-08-13 16:56:26 +02003368 LY_ERR ret = LY_SUCCESS;
3369 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003370 struct lysp_submodule *dup;
David Sedlák3b4db242018-10-19 16:11:01 +02003371
Michal Vaskob36053d2020-03-26 15:49:30 +01003372 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3373 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 +02003374 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003375 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3376 LY_STMT_ANYXML, &mod->data, 0,
3377 LY_STMT_AUGMENT, &mod->augments, 0,
3378 LY_STMT_CHOICE, &mod->data, 0,
3379 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3380 LY_STMT_CONTAINER, &mod->data, 0,
3381 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3382 LY_STMT_DEVIATION, &mod->deviations, 0,
3383 LY_STMT_EXTENSION, &mod->extensions, 0,
3384 LY_STMT_FEATURE, &mod->features, 0,
3385 LY_STMT_GROUPING, &mod->groupings, 0,
3386 LY_STMT_IDENTITY, &mod->identities, 0,
3387 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3388 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3389 LY_STMT_LEAF, &mod->data, 0,
3390 LY_STMT_LEAF_LIST, &mod->data, 0,
3391 LY_STMT_LIST, &mod->data, 0,
3392 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3393 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3394 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3395 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3396 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3397 LY_STMT_REVISION, &mod->revs, 0,
3398 LY_STMT_RPC, &mod->rpcs, 0,
3399 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3400 LY_STMT_USES, &mod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003401 LY_STMT_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003402 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003403 ));
3404
Michal Vaskob36053d2020-03-26 15:49:30 +01003405 ret = yin_parse_content(ctx, subelems, 28, LY_STMT_MODULE, NULL, &mod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003406 subelems_deallocator(28, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003407 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003408
David Sedláked809f12019-09-13 10:15:11 +02003409 /* finalize parent pointers to the reallocated items */
3410 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
3411
3412 /* submodules share the namespace with the module names, so there must not be
3413 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003414 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, mod->mod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003415 if (dup) {
3416 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
3417 return LY_EVALID;
3418 }
3419
3420 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003421}
3422
3423LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003424yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003425{
David Sedlák81497a32019-08-13 16:56:26 +02003426 LY_ERR ret = LY_SUCCESS;
3427 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003428 struct lysp_submodule *dup;
David Sedlák298ff6d2019-07-26 14:29:03 +02003429
Michal Vaskob36053d2020-03-26 15:49:30 +01003430 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3431 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 +02003432 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003433 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3434 LY_STMT_ANYXML, &submod->data, 0,
3435 LY_STMT_AUGMENT, &submod->augments, 0,
3436 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3437 LY_STMT_CHOICE, &submod->data, 0,
3438 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3439 LY_STMT_CONTAINER, &submod->data, 0,
3440 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3441 LY_STMT_DEVIATION, &submod->deviations, 0,
3442 LY_STMT_EXTENSION, &submod->extensions, 0,
3443 LY_STMT_FEATURE, &submod->features, 0,
3444 LY_STMT_GROUPING, &submod->groupings, 0,
3445 LY_STMT_IDENTITY, &submod->identities, 0,
3446 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3447 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3448 LY_STMT_LEAF, &submod->data, 0,
3449 LY_STMT_LEAF_LIST, &submod->data, 0,
3450 LY_STMT_LIST, &submod->data, 0,
3451 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3452 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3453 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3454 LY_STMT_REVISION, &submod->revs, 0,
3455 LY_STMT_RPC, &submod->rpcs, 0,
3456 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3457 LY_STMT_USES, &submod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003458 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003459 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003460 ));
3461
Michal Vaskob36053d2020-03-26 15:49:30 +01003462 ret = yin_parse_content(ctx, subelems, 27, LY_STMT_SUBMODULE, NULL, &submod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003463 subelems_deallocator(27, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003464 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003465
David Sedláked809f12019-09-13 10:15:11 +02003466 /* finalize parent pointers to the reallocated items */
3467 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
3468
3469 /* submodules share the namespace with the module names, so there must not be
3470 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003471 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, submod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003472 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
3473 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
3474 return LY_EVALID;
3475 }
3476
3477 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003478}
3479
3480LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003481yin_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 +02003482{
Radek Krejcid6b76452019-09-03 17:03:03 +02003483 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003484 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003485 struct lysp_submodule *mod_p = NULL;
3486
3487 /* create context */
3488 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003489 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003490 (*yin_ctx)->format = LYS_IN_YIN;
3491 LY_CHECK_RET(lyxml_ctx_new(ctx, data, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003492
David Sedlák1b623122019-08-05 15:27:49 +02003493 /* map the typedefs and groupings list from main context to the submodule's context */
3494 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3495 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3496
David Sedlák8985a142019-07-31 16:43:06 +02003497 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003498 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
3499 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003500 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003501 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3502 ret = LY_EINVAL;
3503 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003504 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003505 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003506 ret = LY_EVALID;
3507 goto cleanup;
3508 }
3509
3510 mod_p = calloc(1, sizeof *mod_p);
3511 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3512 mod_p->parsing = 1;
3513
Michal Vaskob36053d2020-03-26 15:49:30 +01003514 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003515 LY_CHECK_GOTO(ret, cleanup);
3516
David Sedlákbf8a2b72019-08-14 16:48:10 +02003517 /* skip possible trailing whitespaces at end of the input */
Michal Vaskob36053d2020-03-26 15:49:30 +01003518 data = (*yin_ctx)->xmlctx->input;
3519 while (*data && isspace(*data)) {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003520 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003521 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003522 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003523 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 +02003524 ret = LY_EVALID;
3525 goto cleanup;
3526 }
3527
David Sedlák8985a142019-07-31 16:43:06 +02003528 mod_p->parsing = 0;
3529 *submod = mod_p;
3530
3531cleanup:
3532 if (ret) {
3533 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003534 yin_parser_ctx_free(*yin_ctx);
3535 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003536 }
David Sedlák8985a142019-07-31 16:43:06 +02003537 return ret;
3538}
3539
3540LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003541yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003542{
David Sedláke4889912018-11-02 09:52:40 +01003543 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003544 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003545 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003546
David Sedlák8985a142019-07-31 16:43:06 +02003547 /* create context */
3548 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003549 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003550 (*yin_ctx)->format = LYS_IN_YIN;
3551 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, data, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003552
David Sedlák8985a142019-07-31 16:43:06 +02003553 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003554 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
3555 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003556 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003557 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 +01003558 ret = LY_EINVAL;
3559 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003560 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003561 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003562 ret = LY_EVALID;
3563 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003564 }
3565
David Sedlák3017da42019-02-15 09:48:04 +01003566 /* allocate module */
3567 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003568 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003569 mod_p->mod = mod;
3570 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003571
David Sedlák00250342019-06-21 14:19:39 +02003572 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003573 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003574 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003575
David Sedlákbf8a2b72019-08-14 16:48:10 +02003576 /* skip possible trailing whitespaces at end of the input */
Michal Vaskob36053d2020-03-26 15:49:30 +01003577 data = (*yin_ctx)->xmlctx->input;
3578 while (*data && isspace(*data)) {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003579 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003580 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003581 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003582 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 +02003583 ret = LY_EVALID;
3584 goto cleanup;
3585 }
3586
David Sedlák3017da42019-02-15 09:48:04 +01003587 mod_p->parsing = 0;
3588 mod->parsed = mod_p;
3589
3590cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003591 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003592 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003593 yin_parser_ctx_free(*yin_ctx);
3594 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003595 }
David Sedlák2e411422018-12-17 02:35:39 +01003596 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003597}