blob: dc48f6d30b97e15bbc88b664a3a688fad36fbdec [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 Krejcica376bd2020-06-11 16:04:06 +020029#include "parser_schema.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020030#include "set.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020031#include "tree.h"
32#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020033#include "tree_schema_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020034#include "xml.h"
David Sedlák00250342019-06-21 14:19:39 +020035
David Sedlák2b214ac2019-06-06 16:11:03 +020036/**
37 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020038 *
David Sedlák2b214ac2019-06-06 16:11:03 +020039 * @param ns Namespace URI to check.
40 *
41 * @return true if ns equals YIN_NS_URI false otherwise.
42 */
43#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
44
David Sedlákf6251182019-06-06 10:22:13 +020045const char *const yin_attr_list[] = {
46 [YIN_ARG_NAME] = "name",
47 [YIN_ARG_TARGET_NODE] = "target-node",
48 [YIN_ARG_MODULE] = "module",
49 [YIN_ARG_VALUE] = "value",
50 [YIN_ARG_TEXT] = "text",
51 [YIN_ARG_CONDITION] = "condition",
52 [YIN_ARG_URI] = "uri",
53 [YIN_ARG_DATE] = "date",
54 [YIN_ARG_TAG] = "tag",
David Sedlák071f7662019-09-12 02:02:51 +020055 [YIN_ARG_NONE] = "none",
David Sedlákf6251182019-06-06 10:22:13 +020056};
57
Radek Krejcid6b76452019-09-03 17:03:03 +020058enum ly_stmt
Michal Vaskob36053d2020-03-26 15:49:30 +010059yin_match_keyword(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejcid6b76452019-09-03 17:03:03 +020060 const char *prefix, size_t prefix_len, enum ly_stmt parrent)
David Sedlák1bccdfa2019-06-17 15:55:27 +020061{
David Sedlák8f7a1172019-06-20 14:42:18 +020062 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +020063 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020064 const struct lyxml_ns *ns = NULL;
65
66 if (!name || name_len == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +020067 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +020068 }
69
Michal Vaskob36053d2020-03-26 15:49:30 +010070 ns = lyxml_ns_get(ctx->xmlctx, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +020071 if (ns) {
72 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +020073 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +020074 }
75 } else {
76 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +020077 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020078 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020079
David Sedlák8f7a1172019-06-20 14:42:18 +020080 start = name;
81 kw = lysp_match_kw(NULL, &name);
82
83 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +020084 /* 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 +020085 if (kw == LY_STMT_VALUE && parrent == LY_STMT_ERROR_MESSAGE) {
86 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +020087 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020088 return kw;
89 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020090 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +020091 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +020092 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +020093 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +020094 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020095 }
96}
97
David Sedlákc5b20842019-08-13 10:18:31 +020098enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +020099yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200100{
David Sedlákc5b20842019-08-13 10:18:31 +0200101 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200102 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200103 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200104
David Sedlák94de2aa2019-02-15 12:42:11 +0100105#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
106#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100107#define IF_ARG_PREFIX_END }
108
David Sedlák1c8b2702019-02-22 11:03:02 +0100109 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100110 case 'c':
111 already_read += 1;
112 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200113 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200114
David Sedlák94de2aa2019-02-15 12:42:11 +0100115 case 'd':
116 already_read += 1;
117 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200118 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200119
David Sedlák94de2aa2019-02-15 12:42:11 +0100120 case 'm':
121 already_read += 1;
122 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200123 break;
124
David Sedlák94de2aa2019-02-15 12:42:11 +0100125 case 'n':
126 already_read += 1;
127 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200128 break;
129
David Sedlák94de2aa2019-02-15 12:42:11 +0100130 case 't':
131 already_read += 1;
132 IF_ARG_PREFIX("a", 1)
133 IF_ARG("g", 1, YIN_ARG_TAG)
134 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
135 IF_ARG_PREFIX_END
136 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200137 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200138
David Sedlák94de2aa2019-02-15 12:42:11 +0100139 case 'u':
140 already_read += 1;
141 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200142 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200143
David Sedlák94de2aa2019-02-15 12:42:11 +0100144 case 'v':
145 already_read += 1;
146 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200147 break;
148 }
149
David Sedlákc10e7902018-12-17 02:17:59 +0100150 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200151 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200152 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200153 }
154
David Sedlák18730132019-03-15 15:51:34 +0100155#undef IF_ARG
156#undef IF_ARG_PREFIX
157#undef IF_ARG_PREFIX_END
158
David Sedlák872c7b42018-10-26 13:15:20 +0200159 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200160}
161
Radek Krejcid6b76452019-09-03 17:03:03 +0200162#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
163 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
164 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
165 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200166
Radek Krejcid6b76452019-09-03 17:03:03 +0200167#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 +0200168
David Sedlák26ea1432019-08-14 13:42:23 +0200169/**
170 * @brief Free subelems information allocated on heap.
171 *
172 * @param[in] count Size of subelems array.
173 * @param[in] subelems Subelems array to free.
174 */
David Sedlák81497a32019-08-13 16:56:26 +0200175static void
176subelems_deallocator(size_t count, struct yin_subelement *subelems)
177{
178 for(size_t i = 0; i < count; ++i) {
179 if (HAS_META(subelems[i].type)) {
180 free(subelems[i].dest);
181 }
182 }
183
184 free(subelems);
185}
186
David Sedlák26ea1432019-08-14 13:42:23 +0200187/**
188 * @brief Allocate subelems information on heap.
189 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200190 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200191 * @param[in] count Number of subelements.
192 * @param[in] parent Parent node if any.
193 * @param[out] result Allocated subelems array.
194 *
195 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
196 */
David Sedlák81497a32019-08-13 16:56:26 +0200197static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100198subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
David Sedlák81497a32019-08-13 16:56:26 +0200199 struct yin_subelement **result, ...)
200{
201 va_list ap;
202
203 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200204 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200205
206 va_start(ap, result);
207 for (size_t i = 0; i < count; ++i) {
208 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200209 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200210 /* DEST */
211 if (IS_NODE_ELEM((*result)[i].type)) {
212 struct tree_node_meta *node_meta = NULL;
213 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200214 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200215 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200216 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200217 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200218 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200219 struct import_meta *imp_meta = NULL;
220 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200221 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200222 imp_meta->prefix = va_arg(ap, const char *);
223 imp_meta->imports = va_arg(ap, struct lysp_import **);
224 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200225 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200226 struct include_meta *inc_meta = NULL;
227 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200228 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200229 inc_meta->name = va_arg(ap, const char *);
230 inc_meta->includes = va_arg(ap, struct lysp_include **);
231 (*result)[i].dest = inc_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200232 } else if ((*result)[i].type == LY_STMT_INPUT || (*result)[i].type == LY_STMT_OUTPUT) {
David Sedlák81497a32019-08-13 16:56:26 +0200233 struct inout_meta *inout_meta = NULL;
234 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200235 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200236 inout_meta->parent = parent;
237 inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
238 (*result)[i].dest = inout_meta;
239 } else {
240 (*result)[i].dest = va_arg(ap, void *);
241 }
242 /* FLAGS */
243 (*result)[i].flags = va_arg(ap, int);
244 }
245 va_end(ap);
246
247 return LY_SUCCESS;
248
David Sedlákbf8a2b72019-08-14 16:48:10 +0200249mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200250 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100251 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200252 return LY_EMEM;
253}
254
David Sedlák8f7a1172019-06-20 14:42:18 +0200255LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100256yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200257{
258 int prefix = 0;
259 unsigned int c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100260 size_t utf8_char_len, already_read = 0;
261 const char *val;
262
263 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
264
265 val = ctx->xmlctx->value;
266 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200267 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
268 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
269 already_read += utf8_char_len;
Michal Vaskob36053d2020-03-26 15:49:30 +0100270 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200271
272 switch (val_type) {
273 case Y_IDENTIF_ARG:
274 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
275 break;
276 case Y_PREF_IDENTIF_ARG:
277 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
278 break;
279 case Y_STR_ARG:
280 case Y_MAYBE_STR_ARG:
281 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
282 break;
283 }
284 }
285
286 return LY_SUCCESS;
287}
288
David Sedlákb4e44562019-07-04 15:42:12 +0200289/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100290 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200291 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200292 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200293 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
294 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200295 * @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 +0200296 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200297 * @param[in] current_element Identification of current element, used for logging.
298 *
299 * @return LY_ERR values.
300 */
301static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100302yin_parse_attribute(struct lys_yin_parser_ctx *ctx, enum yin_argument arg_type, const char **arg_val, enum yang_arg val_type,
303 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200304{
David Sedlákc5b20842019-08-13 10:18:31 +0200305 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200306 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200307
David Sedlák1bccdfa2019-06-17 15:55:27 +0200308 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100309 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200310 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100311 if (!ctx->xmlctx->prefix) {
312 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200313 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100314 /* skip it */
315 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200316 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200317 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
David Sedlák292763b2019-07-09 11:10:53 +0200318 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200319 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100320
321 /* go to value */
322 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
323 LY_CHECK_RET(yin_validate_value(ctx, val_type));
324 *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 +0200325 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200326 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100327 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
328 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200329 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200330 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100331 } else {
332 /* skip it */
333 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200334 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100335
336 /* next attribute */
337 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200338 }
339
David Sedlák292763b2019-07-09 11:10:53 +0200340 /* anything else than Y_MAYBE_STR_ARG is mandatory */
341 if (val_type != Y_MAYBE_STR_ARG && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100342 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
343 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200344 return LY_EVALID;
345 }
346
347 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200348}
349
David Sedlákd6e56892019-07-01 15:40:24 +0200350/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200351 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200352 *
353 * @param[in] type Type of wanted record.
354 * @param[in] array_size Size of array.
355 * @param[in] array Searched array.
356 *
357 * @return Pointer to desired record on success, NULL if element is not in the array.
358 */
David Sedlákb4e44562019-07-04 15:42:12 +0200359static struct yin_subelement *
Radek Krejci12b1c152019-09-05 16:20:48 +0200360get_record(enum ly_stmt type, size_t array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200361{
Radek Krejci12b1c152019-09-05 16:20:48 +0200362 for (unsigned int u = 0; u < array_size; ++u) {
363 if (array[u].type == type) {
364 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200365 }
366 }
David Sedlákd6e56892019-07-01 15:40:24 +0200367 return NULL;
368}
369
David Sedlákbba38e52019-07-09 15:20:01 +0200370/**
371 * @brief Helper function to check mandatory constraint of subelement.
372 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200373 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200374 * @param[in] subelem_info Array of information about subelements.
375 * @param[in] subelem_info_size Size of subelem_info array.
376 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
377 *
378 * @return LY_ERR values.
379 */
380static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100381yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200382 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200383{
David Sedlákb0faad82019-07-04 14:28:59 +0200384 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200385 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200386 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200387 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200388 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200389 return LY_EVALID;
390 }
391 }
392
393 return LY_SUCCESS;
394}
395
David Sedlákbba38e52019-07-09 15:20:01 +0200396/**
397 * @brief Helper function to check "first" constraint of subelement.
398 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200399 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200400 * @param[in] subelem_info Array of information about subelements.
401 * @param[in] subelem_info_size Size of subelem_info array.
402 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200403 * @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 +0200404 *
405 * @return LY_ERR values.
406 */
407static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100408yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200409 signed char subelem_info_size, enum ly_stmt current_element,
David Sedláke1a30302019-07-10 13:49:38 +0200410 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200411{
David Sedlákb0faad82019-07-04 14:28:59 +0200412 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200413 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200414 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
415 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200416 return LY_EVALID;
417 }
418 }
419
420 return LY_SUCCESS;
421}
422
David Sedlákbba38e52019-07-09 15:20:01 +0200423/**
David Sedlákb4e44562019-07-04 15:42:12 +0200424 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
425 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200426 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200427 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200428 * @param[in] kw Type of current element.
429 * @param[out] value Where value of attribute should be stored.
430 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200431 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200432 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200433 * @return LY_ERR values.
434 */
David Sedlákb4e44562019-07-04 15:42:12 +0200435static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100436yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
437 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200438{
Michal Vaskob36053d2020-03-26 15:49:30 +0100439 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
440 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200441 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200442 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200443 };
David Sedlákb4e44562019-07-04 15:42:12 +0200444
Michal Vaskob36053d2020-03-26 15:49:30 +0100445 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200446}
447
448/**
David Sedlák6542aed2019-08-14 10:47:43 +0200449 * @brief Parse path element.
450 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200451 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200452 * @param[in] kw Type of current element.
453 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200454 * @return LY_ERR values.
455 */
456static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100457yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200458{
Michal Vasko004d3152020-06-11 19:59:22 +0200459 LY_ERR ret;
460 const char *str_path;
461
462 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, &str_path, YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
463 ret = ly_path_parse(ctx->xmlctx->ctx, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
464 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
465 lydict_remove(ctx->xmlctx->ctx, str_path);
466 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200467 type->flags |= LYS_SET_PATH;
468
469 return LY_SUCCESS;
470}
471
472/**
David Sedlákd3983112019-07-12 11:20:56 +0200473 * @brief Parse pattern element.
474 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200475 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200476 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200477 * @return LY_ERR values.
478 */
479static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100480yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200481{
482 const char *real_value = NULL;
483 char *saved_value = NULL;
484 struct lysp_restr *restr;
485
Michal Vaskob36053d2020-03-26 15:49:30 +0100486 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
487 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
488 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 +0200489 size_t len = strlen(real_value);
490
491 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100492 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200493 memmove(saved_value + 1, real_value, len);
Michal Vaskob36053d2020-03-26 15:49:30 +0100494 FREE_STRING(ctx->xmlctx->ctx, real_value);
David Sedlákd3983112019-07-12 11:20:56 +0200495 saved_value[0] = 0x06;
496 saved_value[len + 1] = '\0';
Michal Vaskob36053d2020-03-26 15:49:30 +0100497 restr->arg = lydict_insert_zc(ctx->xmlctx->ctx, saved_value);
498 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200499 type->flags |= LYS_SET_PATTERN;
500
501 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200502 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
503 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
504 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
505 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
506 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
507 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákd3983112019-07-12 11:20:56 +0200508 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100509 return yin_parse_content(ctx, subelems, 6, LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200510}
511
David Sedlákc5b20842019-08-13 10:18:31 +0200512/**
513 * @brief Parse fraction-digits element.
514 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200515 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200516 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200517 * @return LY_ERR values.
518 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200519static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100520yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200521{
522 const char *temp_val = NULL;
523 char *ptr;
524 unsigned long int num;
525
Michal Vaskob36053d2020-03-26 15:49:30 +0100526 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
527 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 +0200528
529 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200530 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100531 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200532 return LY_EVALID;
533 }
534
535 errno = 0;
536 num = strtoul(temp_val, &ptr, 10);
537 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200538 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100539 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200540 return LY_EVALID;
541 }
542 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200543 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100544 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200545 return LY_EVALID;
546 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100547 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200548 type->fraction_digits = num;
549 type->flags |= LYS_SET_FRDIGITS;
550 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200551 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200552 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100553 return yin_parse_content(ctx, subelems, 1, LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200554}
555
David Sedlák07869a52019-07-12 14:28:19 +0200556/**
David Sedlák43801c92019-08-05 15:58:54 +0200557 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200558 *
559 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200560 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200561 * @return LY_ERR values.
562 */
David Sedlákca36c422019-07-12 12:47:55 +0200563static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100564yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200565{
David Sedlák07869a52019-07-12 14:28:19 +0200566 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200567
Michal Vaskob36053d2020-03-26 15:49:30 +0100568 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200569 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100570 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
571 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 +0200572 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100573 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200574 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200575
576 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200577 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
578 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
579 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
580 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
581 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
582 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákca36c422019-07-12 12:47:55 +0200583 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100584 return yin_parse_content(ctx, subelems, 6, LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200585}
586
587/**
588 * @brief Parse bit element.
589 *
590 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200591 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200592 * @return LY_ERR values.
593 */
594static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100595yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200596{
597 struct lysp_type_enum *en;
598
Michal Vaskob36053d2020-03-26 15:49:30 +0100599 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200600 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100601 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
602 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 +0200603 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
604
605 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200606 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
607 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
608 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
609 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
610 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
611 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák43801c92019-08-05 15:58:54 +0200612 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100613 return yin_parse_content(ctx, subelems, 6, LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200614}
615
David Sedlákd3983112019-07-12 11:20:56 +0200616/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200617 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
618 * more instances, such as base or if-feature.
619 *
620 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200621 * @param[in] kw Type of current element.
622 * @param[out] values Parsed values to add to.
623 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200624 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200625 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200626 * @return LY_ERR values.
627 */
628static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100629yin_parse_simple_elements(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char ***values, enum yin_argument arg_type,
630 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200631{
632 const char **value;
Michal Vaskob36053d2020-03-26 15:49:30 +0100633 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Radek Krejci7eb54ba2020-05-18 16:30:04 +0200634 LY_ARRAY_SIZE_TYPE index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200635 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200636 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200637 };
638
Michal Vaskob36053d2020-03-26 15:49:30 +0100639 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
640 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200641
Michal Vaskob36053d2020-03-26 15:49:30 +0100642 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200643}
644
645/**
David Sedlák6542aed2019-08-14 10:47:43 +0200646 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
647 *
648 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200649 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200650 * @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 +0200651 * @param[in] arg_type Expected type of attribute.
652 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200653 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200654 * @return LY_ERR values.
655 */
656static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100657yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
658 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200659{
660 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100661 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200662 arg_type, arg_val_type, exts));
663 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100664 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200665 arg_type, arg_val_type, exts));
666 }
667
668 return LY_SUCCESS;
669}
670
671/**
672 * @brief Parse base element.
673 *
674 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200675 * @param[in] parent Identification of parent element.
676 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200677 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200678 * @return LY_ERR values.
679 */
680static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100681yin_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 +0200682{
683 struct lysp_type *type = NULL;
684
Radek Krejcid6b76452019-09-03 17:03:03 +0200685 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200686 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100687 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
David Sedlák6542aed2019-08-14 10:47:43 +0200688 Y_PREF_IDENTIF_ARG, exts));
689 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200690 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100691 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200692 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
693 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100694 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200695 return LY_EINT;
696 }
697
698 return LY_SUCCESS;
699}
700
701/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200702 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200703 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200704 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100705 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200706 * @return LY_ERR values.
707 */
708static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100709yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200710{
711 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200712 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200713 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200714 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200715
716 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100717 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
718 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 +0200719 if (strcmp(temp_val, "true") == 0) {
720 type->require_instance = 1;
721 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200722 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
723 "require-instance", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +0100724 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200725 return LY_EVALID;
726 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100727 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200728
Michal Vaskob36053d2020-03-26 15:49:30 +0100729 return yin_parse_content(ctx, subelems, 1, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200730}
731
732/**
David Sedlákce77bf52019-07-11 16:59:31 +0200733 * @brief Parse modifier element.
734 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200735 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200736 * @param[in,out] pat Value to write to.
737 * @param[in,out] exts Extension instances to add to.
738 *
739 * @return LY_ERR values.
740 */
741static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100742yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200743{
David Sedlákd3983112019-07-12 11:20:56 +0200744 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200745 const char *temp_val;
746 char *modified_val;
747 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200748 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákce77bf52019-07-11 16:59:31 +0200749 };
750
Michal Vaskob36053d2020-03-26 15:49:30 +0100751 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
752 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 +0200753 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200754 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
755 "modifier", "invert-match");
Michal Vaskob36053d2020-03-26 15:49:30 +0100756 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200757 return LY_EVALID;
758 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100759 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200760
761 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200762 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100763 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200764 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100765 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200766
767 /* modify the new value */
768 modified_val[0] = 0x15;
Michal Vaskob36053d2020-03-26 15:49:30 +0100769 *pat = lydict_insert_zc(ctx->xmlctx->ctx, modified_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200770
Michal Vaskob36053d2020-03-26 15:49:30 +0100771 return yin_parse_content(ctx, subelems, 1, LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200772}
773
774/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200775 * @brief Parse a restriction element (length, range or one instance of must).
776 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200777 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200778 * @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 +0200779 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200780 */
781static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100782yin_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 +0200783{
Radek Krejcid6b76452019-09-03 17:03:03 +0200784 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
David Sedlákb7296dd2019-07-11 14:58:38 +0200785 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200786 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
787 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
788 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
789 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
790 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200791 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200792 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200793 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200794
Michal Vaskob36053d2020-03-26 15:49:30 +0100795 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
796 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
797
798 return yin_parse_content(ctx, subelems, 5, restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200799}
800
801/**
David Sedlák6542aed2019-08-14 10:47:43 +0200802 * @brief Parse range element.
803 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200804 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200805 * @param[out] type Type structure to store parsed value and flags.
806 *
807 * @return LY_ERR values.
808 */
809static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100810yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200811{
812 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100813 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
814 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
David Sedlák6542aed2019-08-14 10:47:43 +0200815 type->flags |= LYS_SET_RANGE;
816
817 return LY_SUCCESS;
818}
819
820/**
821 * @brief Parse length element.
822 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200823 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200824 * @param[out] type Type structure to store parsed value and flags.
825 *
826 * @return LY_ERR values.
827 */
828static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100829yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200830{
831 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100832 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
833 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200834 type->flags |= LYS_SET_LENGTH;
835
836 return LY_SUCCESS;
837}
838
839/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200840 * @brief Parse must element.
841 *
842 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200843 * @param[in,out] restrs Restrictions to add to.
844 *
845 * @return LY_ERR values.
846 */
847static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100848yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200849{
850 struct lysp_restr *restr;
851
Michal Vaskob36053d2020-03-26 15:49:30 +0100852 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
853 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200854}
855
856/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200857 * @brief Parse position or value element.
858 *
859 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200860 * @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 +0200861 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200862 *
863 * @return LY_ERR values.
864 */
865static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100866yin_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 +0200867{
Radek Krejcid6b76452019-09-03 17:03:03 +0200868 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +0200869 const char *temp_val = NULL;
870 char *ptr;
871 long int num;
872 unsigned long int unum;
873
874 /* set value flag */
875 enm->flags |= LYS_SET_VALUE;
876
877 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +0100878 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
879 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
David Sedlákae5378f2019-07-17 11:37:59 +0200880 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
Radek Krejcid6b76452019-09-03 17:03:03 +0200881 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200882 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +0200883 goto error;
884 }
885
886 /* convert value */
887 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +0200888 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200889 num = strtol(temp_val, &ptr, 10);
890 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200891 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 +0200892 goto error;
893 }
894 } else {
895 unum = strtoul(temp_val, &ptr, 10);
896 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200897 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 +0200898 goto error;
899 }
900 }
901 /* check if whole argument value was converted */
902 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200903 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 +0200904 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200905 }
906 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +0200907 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 +0200908 goto error;
909 }
910 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +0200911 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200912 enm->value = num;
913 } else {
914 enm->value = unum;
915 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100916 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +0200917
918 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200919 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200920 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200921 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100922 return yin_parse_content(ctx, subelems, 1, kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +0200923
David Sedlákbf8a2b72019-08-14 16:48:10 +0200924error:
Michal Vaskob36053d2020-03-26 15:49:30 +0100925 FREE_STRING(ctx->xmlctx->ctx, temp_val);
926 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +0200927}
928
David Sedlák05404f62019-07-24 14:11:53 +0200929/**
930 * @brief Parse belongs-to element.
931 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200932 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +0200933 * @param[out] submod Structure of submodule that is being parsed.
934 * @param[in,out] exts Extension instances to add to.
935 *
936 * @return LY_ERR values
937 */
938static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100939yin_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 +0200940{
941 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200942 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
943 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák05404f62019-07-24 14:11:53 +0200944 };
David Sedlák05404f62019-07-24 14:11:53 +0200945
Michal Vaskob36053d2020-03-26 15:49:30 +0100946 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
947 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
948
949 return yin_parse_content(ctx, subelems, 2, LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +0200950}
951
David Sedlák5545f5d2019-07-11 11:55:16 +0200952/**
David Sedlákc1771b12019-07-10 15:55:46 +0200953 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +0200954 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +0200955 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200956 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200957 * @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 +0200958 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200959 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200960 *
961 * @return LY_ERR values.
962 */
963static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100964yin_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 +0200965{
Radek Krejcid6b76452019-09-03 17:03:03 +0200966 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 +0200967
David Sedlák968ac342019-07-11 15:17:59 +0200968 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200969 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
970 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +0200971 };
David Sedlákdf2a9732019-08-07 13:23:16 +0200972 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100973 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
974 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 +0200975
David Sedlákdf2a9732019-08-07 13:23:16 +0200976 /* parse content */
Michal Vaskob36053d2020-03-26 15:49:30 +0100977 return yin_parse_content(ctx, subelems, 2, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200978}
979
980/**
David Sedlákc1771b12019-07-10 15:55:46 +0200981 * @brief Parse error-message element.
982 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200983 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +0200984 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200985 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +0200986 *
987 * @return LY_ERR values.
988 */
989static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100990yin_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 +0200991{
David Sedlák968ac342019-07-11 15:17:59 +0200992 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200993 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
994 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +0200995 };
David Sedlákc1771b12019-07-10 15:55:46 +0200996
David Sedlákdf2a9732019-08-07 13:23:16 +0200997 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100998 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
999 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 +02001000
Michal Vaskob36053d2020-03-26 15:49:30 +01001001 return yin_parse_content(ctx, subelems, 2, LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001002}
1003
1004/**
David Sedlák6542aed2019-08-14 10:47:43 +02001005 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001006 *
1007 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001008 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001009 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001010 *
1011 * @return LY_ERR values.
1012 */
1013static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001014yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001015{
David Sedlák6542aed2019-08-14 10:47:43 +02001016 struct lysp_type *type = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +02001017 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001018 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001019 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001020 type = *((struct lysp_type **)subinfo->dest);
1021 } else {
1022 type = (struct lysp_type *)subinfo->dest;
1023 }
1024 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001025 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001026 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001027 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001028 type->flags |= LYS_SET_TYPE;
1029 type = nested_type;
1030 }
David Sedlák374d2b32019-07-17 15:06:55 +02001031 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001032 {LY_STMT_BASE, type, 0},
1033 {LY_STMT_BIT, type, 0},
1034 {LY_STMT_ENUM, type, 0},
1035 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1036 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1037 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1038 {LY_STMT_PATTERN, type, 0},
1039 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1040 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1041 {LY_STMT_TYPE, type},
1042 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák374d2b32019-07-17 15:06:55 +02001043 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001044
1045 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1046 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1047 return yin_parse_content(ctx, subelems, 11, LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001048}
1049
David Sedlák1af868e2019-07-17 17:03:14 +02001050/**
1051 * @brief Parse max-elements element.
1052 *
1053 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001054 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001055 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001056 * @param[in,out] exts Extension instances to add to.
1057 *
1058 * @return LY_ERR values.
1059 */
1060static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001061yin_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 +02001062{
1063 const char *temp_val = NULL;
1064 char *ptr;
1065 unsigned long int num;
1066 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001067 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák1af868e2019-07-17 17:03:14 +02001068 };
David Sedlák374d2b32019-07-17 15:06:55 +02001069
David Sedlák1af868e2019-07-17 17:03:14 +02001070 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001071 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1072 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 +02001073 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 +02001074 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001075 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001076 return LY_EVALID;
1077 }
1078
1079 if (strcmp(temp_val, "unbounded")) {
1080 errno = 0;
1081 num = strtoul(temp_val, &ptr, 10);
1082 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001083 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001084 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001085 return LY_EVALID;
1086 }
1087 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001088 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001089 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001090 return LY_EVALID;
1091 }
1092 *max = num;
1093 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001094 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1095 return yin_parse_content(ctx, subelems, 1, LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001096}
David Sedlák374d2b32019-07-17 15:06:55 +02001097
1098/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001099 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001100 *
1101 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001102 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001103 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001104 * @param[in,out] exts Extension instances to add to.
1105 *
1106 * @return LY_ERR values.
1107 */
1108static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001109yin_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 +02001110{
1111 const char *temp_val = NULL;
1112 char *ptr;
1113 unsigned long int num;
1114 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001115 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák09e18c92019-07-18 11:17:11 +02001116 };
1117
1118 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001119 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1120 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 +02001121
1122 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001123 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001124 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001125 return LY_EVALID;
1126 }
1127
1128 errno = 0;
1129 num = strtoul(temp_val, &ptr, 10);
1130 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001131 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001132 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001133 return LY_EVALID;
1134 }
1135 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001136 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001137 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001138 return LY_EVALID;
1139 }
1140 *min = num;
Michal Vaskob36053d2020-03-26 15:49:30 +01001141 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1142 return yin_parse_content(ctx, subelems, 1, LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001143}
1144
David Sedláka2dad212019-07-18 12:45:19 +02001145/**
1146 * @brief Parse min-elements or max-elements element.
1147 *
1148 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001149 * @param[in] parent Identification of parent element.
1150 * @param[in] current Identification of current element.
1151 * @param[in] dest Where the parsed value and flags should be stored.
1152 *
1153 * @return LY_ERR values.
1154 */
David Sedlák09e18c92019-07-18 11:17:11 +02001155static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001156yin_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 +02001157{
Radek Krejcid6b76452019-09-03 17:03:03 +02001158 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1159 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 +02001160 uint32_t *lim;
1161 uint16_t *flags;
1162 struct lysp_ext_instance **exts;
1163
Radek Krejcid6b76452019-09-03 17:03:03 +02001164 if (parent == LY_STMT_LEAF_LIST) {
1165 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 +02001166 flags = &((struct lysp_node_leaflist *)dest)->flags;
1167 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001168 } else if (parent == LY_STMT_REFINE) {
1169 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001170 flags = &((struct lysp_refine *)dest)->flags;
1171 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001172 } else if (parent == LY_STMT_LIST) {
1173 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 +02001174 flags = &((struct lysp_node_list *)dest)->flags;
1175 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001176 } else {
1177 lim = ((struct minmax_dev_meta *)dest)->lim;
1178 flags = ((struct minmax_dev_meta *)dest)->flags;
1179 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001180 }
1181
Radek Krejcid6b76452019-09-03 17:03:03 +02001182 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001183 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001184 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001185 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001186 }
1187
1188 return LY_SUCCESS;
1189}
1190
1191/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001192 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001193 *
1194 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001195 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001196 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001197 *
1198 * @return LY_ERR values.
1199 */
1200static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001201yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001202{
1203 const char *temp_val;
1204 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001205 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedláka2dad212019-07-18 12:45:19 +02001206 };
1207
Michal Vaskob36053d2020-03-26 15:49:30 +01001208 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1209 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 +02001210 if (strcmp(temp_val, "system") == 0) {
1211 *flags |= LYS_ORDBY_SYSTEM;
1212 } else if (strcmp(temp_val, "user") == 0) {
1213 *flags |= LYS_ORDBY_USER;
1214 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001215 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1216 "ordered-by", "system", "user");
Michal Vaskob36053d2020-03-26 15:49:30 +01001217 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001218 return LY_EVALID;
1219 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001220 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001221
Michal Vaskob36053d2020-03-26 15:49:30 +01001222 return yin_parse_content(ctx, subelems, 1, LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001223}
1224
1225/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001226 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001227 *
1228 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001229 * @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 +02001230 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001231 *
1232 * @return LY_ERR values.
1233 */
1234static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001235yin_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 +02001236{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001237 struct lysp_node_anydata *any;
1238
David Sedlák8d552d62019-08-06 15:29:05 +02001239 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001240 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001241 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001242 any->parent = node_meta->parent;
1243
David Sedlákbf8a2b72019-08-14 16:48:10 +02001244 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001245 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1246 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 +02001247
1248 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001249 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1250 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1251 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1252 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1253 {LY_STMT_MUST, &any->musts, 0},
1254 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1255 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1256 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1257 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8a83bbb2019-07-18 14:46:00 +02001258 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001259 return yin_parse_content(ctx, subelems, 9, any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001260}
1261
1262/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001263 * @brief parse leaf element.
1264 *
1265 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001266 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001267 *
1268 * @return LY_ERR values.
1269 */
1270static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001271yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001272{
David Sedlák203ca3a2019-07-18 15:26:25 +02001273 struct lysp_node_leaf *leaf;
1274
David Sedlák8d552d62019-08-06 15:29:05 +02001275 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001276 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001277 leaf->nodetype = LYS_LEAF;
1278 leaf->parent = node_meta->parent;
1279
David Sedlák203ca3a2019-07-18 15:26:25 +02001280 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001281 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1282 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 +02001283
1284 /* parse content */
1285 struct yin_subelement subelems[12] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001286 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1287 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1288 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1289 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1290 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1291 {LY_STMT_MUST, &leaf->musts, 0},
1292 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1293 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1294 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1295 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1296 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1297 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001298 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001299 return yin_parse_content(ctx, subelems, 12, LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001300}
1301
1302/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001303 * @brief Parse leaf-list element.
1304 *
1305 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001306 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001307 *
1308 * @return LY_ERR values.
1309 */
1310static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001311yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001312{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001313 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001314
Michal Vaskob36053d2020-03-26 15:49:30 +01001315 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001316
David Sedlákc3da3ef2019-07-19 12:56:08 +02001317 llist->nodetype = LYS_LEAFLIST;
1318 llist->parent = node_meta->parent;
1319
David Sedlákc3da3ef2019-07-19 12:56:08 +02001320 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001321 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1322 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 +02001323
1324 /* parse content */
1325 struct yin_subelement subelems[14] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001326 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1327 {LY_STMT_DEFAULT, &llist->dflts, 0},
1328 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1329 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1330 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1331 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1332 {LY_STMT_MUST, &llist->musts, 0},
1333 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1334 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1335 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1336 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1337 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1338 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1339 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001340 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001341 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001342
David Sedlákbf8a2b72019-08-14 16:48:10 +02001343 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001344 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001345 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001346 return LY_EVALID;
1347 }
1348 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001349 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001350 return LY_EVALID;
1351 }
1352
1353 return LY_SUCCESS;
1354}
1355
1356/**
David Sedlák04e17b22019-07-19 15:29:48 +02001357 * @brief Parse typedef element.
1358 *
1359 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001360 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001361 *
1362 * @return LY_ERR values.
1363 */
1364static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001365yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001366{
1367 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001368 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vaskob36053d2020-03-26 15:49:30 +01001369 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001370
1371 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001372 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1373 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 +02001374
1375 /* parse content */
1376 struct yin_subelement subelems[7] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001377 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1378 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1379 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1380 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1381 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1382 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1383 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001384 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001385 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001386
1387 /* store data for collision check */
Michal Vasko1bf09392020-03-27 12:38:10 +01001388 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 +02001389 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0) == -1, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001390 }
1391
1392 return LY_SUCCESS;
1393}
1394
1395/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001396 * @brief Parse refine element.
1397 *
1398 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001399 * @param[in,out] refines Refines to add to.
1400 *
1401 * @return LY_ERR values.
1402 */
1403static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001404yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001405{
1406 struct lysp_refine *rf;
1407
1408 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001409 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001410
1411 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001412 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1413 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1414 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001415
1416 /* parse content */
1417 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001418 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1419 {LY_STMT_DEFAULT, &rf->dflts, 0},
1420 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1421 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
1422 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1423 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1424 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1425 {LY_STMT_MUST, &rf->musts, 0},
1426 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1427 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1428 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001429 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001430 return yin_parse_content(ctx, subelems, 11, LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001431}
1432
1433/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001434 * @brief Parse uses element.
1435 *
1436 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001437 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001438 *
1439 * @return LY_ERR values.
1440 */
1441static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001442yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001443{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001444 struct lysp_node_uses *uses;
1445
David Sedlák8d552d62019-08-06 15:29:05 +02001446 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001447 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001448 uses->nodetype = LYS_USES;
1449 uses->parent = node_meta->parent;
1450
David Sedlák0d6de5a2019-07-22 13:25:44 +02001451 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001452 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1453 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 +02001454
1455 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001456 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001457 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001458 {LY_STMT_AUGMENT, &augments, 0},
1459 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1460 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1461 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1462 {LY_STMT_REFINE, &uses->refines, 0},
1463 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1464 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1465 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001466 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001467 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001468 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1469
1470 return LY_SUCCESS;
1471}
1472
1473/**
David Sedlákaa854b02019-07-22 14:17:10 +02001474 * @brief Parse revision element.
1475 *
1476 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001477 * @param[in,out] revs Parsed revisions to add to.
1478 *
1479 * @return LY_ERR values.
1480 */
1481static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001482yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001483{
1484 struct lysp_revision *rev;
1485 const char *temp_date = NULL;
1486
1487 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001488 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001489
1490 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001491 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1492 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 +02001493 /* check value */
1494 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001495 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001496 return LY_EVALID;
1497 }
1498 strcpy(rev->date, temp_date);
Michal Vaskob36053d2020-03-26 15:49:30 +01001499 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001500
1501 /* parse content */
1502 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001503 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1504 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1505 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001506 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001507 return yin_parse_content(ctx, subelems, 3, LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001508}
1509
David Sedlák5e13dea2019-07-22 16:06:45 +02001510/**
1511 * @brief Parse include element.
1512 *
1513 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001514 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1515 *
1516 * @return LY_ERR values.
1517 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001518static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001519yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001520{
1521 struct lysp_include *inc;
1522
1523 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001524 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001525
1526 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001527 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1528 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 +02001529
1530 /* submodules share the namespace with the module names, so there must not be
1531 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001532 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 +02001533 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001534 return LY_EVALID;
1535 }
1536
1537 /* parse content */
1538 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001539 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1540 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1541 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1542 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák0c2bab92019-07-22 15:33:19 +02001543 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001544 return yin_parse_content(ctx, subelems, 4, LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001545}
1546
David Sedlákaa854b02019-07-22 14:17:10 +02001547/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001548 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001549 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001550 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001551 * @param[in,out] rev Array to store the parsed value in.
1552 * @param[in,out] exts Extension instances to add to.
1553 *
1554 * @return LY_ERR values.
1555 */
1556static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001557yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001558{
1559 const char *temp_rev;
1560 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001561 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001562 };
1563
Michal Vaskob36053d2020-03-26 15:49:30 +01001564 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1565 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 +02001566 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 +01001567 FREE_STRING(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001568
1569 strcpy(rev, temp_rev);
Michal Vaskob36053d2020-03-26 15:49:30 +01001570 FREE_STRING(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001571
Michal Vaskob36053d2020-03-26 15:49:30 +01001572 return yin_parse_content(ctx, subelems, 1, LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001573}
1574
1575/**
1576 * @brief Parse config element.
1577 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001578 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001579 * @param[in,out] flags Flags to add to.
1580 * @param[in,out] exts Extension instances to add to.
1581 *
1582 * @return LY_ERR values.
1583 */
1584static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001585yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001586{
1587 const char *temp_val = NULL;
1588 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001589 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001590 };
1591
Michal Vaskob36053d2020-03-26 15:49:30 +01001592 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1593 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 +02001594 if (strcmp(temp_val, "true") == 0) {
1595 *flags |= LYS_CONFIG_W;
1596 } else if (strcmp(temp_val, "false") == 0) {
1597 *flags |= LYS_CONFIG_R;
1598 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001599 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
1600 "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001601 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001602 return LY_EVALID;
1603 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001604 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001605
Michal Vaskob36053d2020-03-26 15:49:30 +01001606 return yin_parse_content(ctx, subelems, 1, LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001607}
1608
1609/**
1610 * @brief Parse yang-version element.
1611 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001612 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001613 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001614 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001615 *
1616 * @return LY_ERR values.
1617 */
1618static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001619yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001620{
1621 const char *temp_version = NULL;
1622 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001623 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001624 };
1625
Michal Vaskob36053d2020-03-26 15:49:30 +01001626 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1627 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 +02001628 if (strcmp(temp_version, "1.0") == 0) {
1629 *version = LYS_VERSION_1_0;
1630 } else if (strcmp(temp_version, "1.1") == 0) {
1631 *version = LYS_VERSION_1_1;
1632 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001633 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
1634 "yang-version", "1.0", "1.1");
Michal Vaskob36053d2020-03-26 15:49:30 +01001635 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001636 return LY_EVALID;
1637 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001638 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001639 ctx->mod_version = *version;
1640
Michal Vaskob36053d2020-03-26 15:49:30 +01001641 return yin_parse_content(ctx, subelems, 1, LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001642}
1643
1644/**
1645 * @brief Parse import element.
1646 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001647 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001648 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1649 *
1650 * @return LY_ERR values.
1651 */
1652static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001653yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001654{
1655 struct lysp_import *imp;
1656 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001657 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001658
1659 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001660 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1661 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1662 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1663 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1664 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001665 };
1666
1667 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001668 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1669 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
1670 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001671 /* check prefix validity */
1672 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1673
1674 return LY_SUCCESS;
1675}
1676
1677/**
1678 * @brief Parse mandatory element.
1679 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001680 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001681 * @param[in,out] flags Flags to add to.
1682 * @param[in,out] exts Extension instances to add to.
1683 *
1684 * @return LY_ERR values.
1685 */
1686static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001687yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001688{
1689 const char *temp_val = NULL;
1690 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001691 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001692 };
1693
Michal Vaskob36053d2020-03-26 15:49:30 +01001694 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1695 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 +02001696 if (strcmp(temp_val, "true") == 0) {
1697 *flags |= LYS_MAND_TRUE;
1698 } else if (strcmp(temp_val, "false") == 0) {
1699 *flags |= LYS_MAND_FALSE;
1700 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001701 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1702 "mandatory", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001703 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001704 return LY_EVALID;
1705 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001706 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001707
Michal Vaskob36053d2020-03-26 15:49:30 +01001708 return yin_parse_content(ctx, subelems, 1, LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001709}
1710
1711/**
1712 * @brief Parse status element.
1713 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001714 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001715 * @param[in,out] flags Flags to add to.
1716 * @param[in,out] exts Extension instances to add to.
1717 *
1718 * @return LY_ERR values.
1719 */
1720static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001721yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001722{
1723 const char *value = NULL;
1724 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001725 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001726 };
1727
Michal Vaskob36053d2020-03-26 15:49:30 +01001728 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1729 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 +02001730 if (strcmp(value, "current") == 0) {
1731 *flags |= LYS_STATUS_CURR;
1732 } else if (strcmp(value, "deprecated") == 0) {
1733 *flags |= LYS_STATUS_DEPRC;
1734 } else if (strcmp(value, "obsolete") == 0) {
1735 *flags |= LYS_STATUS_OBSLT;
1736 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001737 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
1738 "status", "current", "deprecated", "obsolete");
Michal Vaskob36053d2020-03-26 15:49:30 +01001739 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001740 return LY_EVALID;
1741 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001742 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001743
Michal Vaskob36053d2020-03-26 15:49:30 +01001744 return yin_parse_content(ctx, subelems, 1, LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001745}
1746
1747/**
1748 * @brief Parse when element.
1749 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001750 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001751 * @param[out] when_p When pointer to parse to.
1752 */
1753static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001754yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001755{
1756 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001757 LY_ERR ret = LY_SUCCESS;
1758
David Sedlákdfbbb442019-08-06 16:33:21 +02001759 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001760 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02001761
1762 ret = lyxml_ctx_next(ctx->xmlctx);
1763 LY_CHECK_ERR_RET(ret, free(when), ret);
1764
Michal Vaskob36053d2020-03-26 15:49:30 +01001765 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001766 LY_CHECK_ERR_RET(ret, free(when), ret);
1767
David Sedlákdfbbb442019-08-06 16:33:21 +02001768 *when_p = when;
1769 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001770 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1771 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1772 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001773 };
1774
Michal Vaskob36053d2020-03-26 15:49:30 +01001775 return yin_parse_content(ctx, subelems, 3, LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001776}
1777
1778/**
1779 * @brief Parse yin-elemenet element.
1780 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001781 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001782 * @param[in,out] data Data to read from, always moved to currently handled position.
1783 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001784 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001785 *
1786 * @return LY_ERR values.
1787 */
1788static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001789yin_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 +02001790{
1791 const char *temp_val = NULL;
1792 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001793 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001794 };
1795
Michal Vaskob36053d2020-03-26 15:49:30 +01001796 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1797 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 +02001798 if (strcmp(temp_val, "true") == 0) {
1799 *flags |= LYS_YINELEM_TRUE;
1800 } else if (strcmp(temp_val, "false") == 0) {
1801 *flags |= LYS_YINELEM_FALSE;
1802 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001803 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1804 "yin-element", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001805 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001806 return LY_EVALID;
1807 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001808 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001809
Michal Vaskob36053d2020-03-26 15:49:30 +01001810 return yin_parse_content(ctx, subelems, 1, LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001811}
1812
1813/**
1814 * @brief Parse argument element.
1815 *
Michal Vaskob36053d2020-03-26 15:49:30 +01001816 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001817 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1818 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001819 *
1820 * @return LY_ERR values.
1821 */
1822static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001823yin_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 +02001824{
1825 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001826 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1827 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001828 };
1829
Michal Vaskob36053d2020-03-26 15:49:30 +01001830 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1831 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 +02001832
Michal Vaskob36053d2020-03-26 15:49:30 +01001833 return yin_parse_content(ctx, subelems, 2, LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001834}
1835
1836/**
1837 * @brief Parse the extension statement.
1838 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001839 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001840 * @param[in,out] extensions Extensions to add to.
1841 *
1842 * @return LY_ERR values.
1843 */
1844static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001845yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02001846{
1847 struct lysp_ext *ex;
Michal Vaskob36053d2020-03-26 15:49:30 +01001848 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
1849 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1850 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 +02001851
1852 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1853 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001854 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1855 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1856 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1857 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1858 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001859 };
1860
Michal Vaskob36053d2020-03-26 15:49:30 +01001861 return yin_parse_content(ctx, subelems, 5, LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001862}
1863
1864/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001865 * @brief Parse feature element.
1866 *
1867 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001868 * @param[in,out] features Features to add to.
1869 *
1870 * @return LY_ERR values.
1871 */
1872static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001873yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02001874{
1875 struct lysp_feature *feat;
1876
1877 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01001878 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02001879
1880 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001881 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1882 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 +02001883
1884 /* parse content */
1885 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001886 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1887 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
1888 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1889 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1890 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák5e13dea2019-07-22 16:06:45 +02001891 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001892 return yin_parse_content(ctx, subelems, 5, LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02001893}
1894
1895/**
David Sedlák28794f22019-07-22 16:45:00 +02001896 * @brief Parse identity element.
1897 *
1898 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02001899 * @param[in,out] identities Identities to add to.
1900 *
1901 * @return LY_ERR values.
1902 */
1903static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001904yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02001905{
1906 struct lysp_ident *ident;
1907
1908 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01001909 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02001910
1911 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001912 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1913 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 +02001914
1915 /* parse content */
1916 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001917 {LY_STMT_BASE, &ident->bases, 0},
1918 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
1919 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
1920 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
1921 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
1922 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák28794f22019-07-22 16:45:00 +02001923 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001924 return yin_parse_content(ctx, subelems, 6, LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02001925}
1926
1927/**
David Sedlákaf536aa2019-07-23 13:42:23 +02001928 * @brief Parse list element.
1929 *
1930 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001931 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02001932 *
1933 * @return LY_ERR values.
1934 */
1935static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001936yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02001937{
David Sedlákaf536aa2019-07-23 13:42:23 +02001938 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02001939 LY_ERR ret = LY_SUCCESS;
1940 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02001941
Michal Vaskob36053d2020-03-26 15:49:30 +01001942 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02001943 list->nodetype = LYS_LIST;
1944 list->parent = node_meta->parent;
1945
David Sedlákaf536aa2019-07-23 13:42:23 +02001946 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001947 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1948 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 +02001949
1950 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02001951 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02001952 LY_STMT_ACTION, &list->actions, 0,
1953 LY_STMT_ANYDATA, &list->child, 0,
1954 LY_STMT_ANYXML, &list->child, 0,
1955 LY_STMT_CHOICE, &list->child, 0,
1956 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
1957 LY_STMT_CONTAINER, &list->child, 0,
1958 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
1959 LY_STMT_GROUPING, &list->groupings, 0,
1960 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
1961 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
1962 LY_STMT_LEAF, &list->child, 0,
1963 LY_STMT_LEAF_LIST, &list->child, 0,
1964 LY_STMT_LIST, &list->child, 0,
1965 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
1966 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
1967 LY_STMT_MUST, &list->musts, 0,
1968 LY_STMT_NOTIFICATION, &list->notifs, 0,
1969 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
1970 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
1971 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
1972 LY_STMT_TYPEDEF, &list->typedefs, 0,
1973 LY_STMT_UNIQUE, &list->uniques, 0,
1974 LY_STMT_USES, &list->child, 0,
1975 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
1976 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02001977 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01001978 ret = yin_parse_content(ctx, subelems, 25, LY_STMT_LIST, NULL, &list->exts);
David Sedlák81497a32019-08-13 16:56:26 +02001979 subelems_deallocator(25, subelems);
1980 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02001981
1982 /* finalize parent pointers to the reallocated items */
1983 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
1984
1985 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001986 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02001987 return LY_EVALID;
1988 }
1989
1990 return LY_SUCCESS;
1991}
1992
1993/**
David Sedlák031b9e72019-07-23 15:19:37 +02001994 * @brief Parse notification element.
1995 *
1996 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001997 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02001998 *
1999 * @return LY_ERR values.
2000 */
2001static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002002yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002003{
2004 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002005 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002006 LY_ERR ret = LY_SUCCESS;
2007 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002008
2009 /* allocate new notification */
Michal Vaskob36053d2020-03-26 15:49:30 +01002010 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002011 notif->nodetype = LYS_NOTIF;
2012 notif->parent = notif_meta->parent;
2013
2014 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002015 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2016 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 +02002017
2018 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002019 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002020 LY_STMT_ANYDATA, &notif->data, 0,
2021 LY_STMT_ANYXML, &notif->data, 0,
2022 LY_STMT_CHOICE, &notif->data, 0,
2023 LY_STMT_CONTAINER, &notif->data, 0,
2024 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2025 LY_STMT_GROUPING, &notif->groupings, 0,
2026 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2027 LY_STMT_LEAF, &notif->data, 0,
2028 LY_STMT_LEAF_LIST, &notif->data, 0,
2029 LY_STMT_LIST, &notif->data, 0,
2030 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2031 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2032 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2033 LY_STMT_TYPEDEF, &notif->typedefs, 0,
2034 LY_STMT_USES, &notif->data, 0,
2035 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002036 ));
2037
Michal Vaskob36053d2020-03-26 15:49:30 +01002038 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_NOTIFICATION, NULL, &notif->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002039 subelems_deallocator(16, subelems);
2040 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002041
2042 /* finalize parent pointers to the reallocated items */
2043 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2044
2045 return LY_SUCCESS;
2046}
2047
2048/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002049 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002050 *
2051 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002052 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002053 *
2054 * @return LY_ERR values.
2055 */
2056static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002057yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002058{
2059 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002060 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002061 LY_ERR ret = LY_SUCCESS;
2062 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002063
2064 /* create new grouping */
Michal Vaskob36053d2020-03-26 15:49:30 +01002065 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002066 grp->nodetype = LYS_GROUPING;
2067 grp->parent = gr_meta->parent;
2068
2069 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002070 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2071 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 +02002072
2073 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002074 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002075 LY_STMT_ACTION, &grp->actions, 0,
2076 LY_STMT_ANYDATA, &grp->data, 0,
2077 LY_STMT_ANYXML, &grp->data, 0,
2078 LY_STMT_CHOICE, &grp->data, 0,
2079 LY_STMT_CONTAINER, &grp->data, 0,
2080 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2081 LY_STMT_GROUPING, &grp->groupings, 0,
2082 LY_STMT_LEAF, &grp->data, 0,
2083 LY_STMT_LEAF_LIST, &grp->data, 0,
2084 LY_STMT_LIST, &grp->data, 0,
2085 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2086 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2087 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2088 LY_STMT_TYPEDEF, &grp->typedefs, 0,
2089 LY_STMT_USES, &grp->data, 0,
2090 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002091 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002092 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_GROUPING, NULL, &grp->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002093 subelems_deallocator(16, subelems);
2094 LY_CHECK_RET(ret);
2095
David Sedláke3ce9ef2019-07-23 16:34:30 +02002096 /* finalize parent pointers to the reallocated items */
2097 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2098
2099 return LY_SUCCESS;
2100}
2101
2102/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002103 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002104 *
2105 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002106 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002107 *
2108 * @return LY_ERR values.
2109 */
2110static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002111yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002112{
David Sedlákf111bcb2019-07-23 17:15:51 +02002113 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002114 LY_ERR ret = LY_SUCCESS;
2115 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002116
2117 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002118 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002119 cont->nodetype = LYS_CONTAINER;
2120 cont->parent = node_meta->parent;
2121
David Sedlákf111bcb2019-07-23 17:15:51 +02002122 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002123 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2124 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 +02002125
2126 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002127 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002128 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2129 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2130 LY_STMT_ANYXML, &cont->child, 0,
2131 LY_STMT_CHOICE, &cont->child, 0,
2132 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2133 LY_STMT_CONTAINER, &cont->child, 0,
2134 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2135 LY_STMT_GROUPING, &cont->groupings, 0,
2136 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2137 LY_STMT_LEAF, &cont->child, 0,
2138 LY_STMT_LEAF_LIST, &cont->child, 0,
2139 LY_STMT_LIST, &cont->child, 0,
2140 LY_STMT_MUST, &cont->musts, 0,
2141 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2142 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2143 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2144 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2145 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2146 LY_STMT_USES, &cont->child, 0,
2147 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2148 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002149 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002150 ret = yin_parse_content(ctx, subelems, 21, LY_STMT_CONTAINER, NULL, &cont->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002151 subelems_deallocator(21, subelems);
2152 LY_CHECK_RET(ret);
2153
David Sedlákf111bcb2019-07-23 17:15:51 +02002154 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2155
2156 return LY_SUCCESS;
2157}
2158
2159/**
David Sedlák5379d392019-07-24 10:42:03 +02002160 * @brief Parse case element.
2161 *
2162 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002163 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002164 *
2165 * @return LY_ERR values.
2166 */
2167static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002168yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002169{
David Sedlák5379d392019-07-24 10:42:03 +02002170 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002171 LY_ERR ret = LY_SUCCESS;
2172 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002173
2174 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002175 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002176 cas->nodetype = LYS_CASE;
2177 cas->parent = node_meta->parent;
2178
David Sedlák5379d392019-07-24 10:42:03 +02002179 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002180 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2181 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 +02002182
2183 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002184 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002185 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2186 LY_STMT_ANYXML, &cas->child, 0,
2187 LY_STMT_CHOICE, &cas->child, 0,
2188 LY_STMT_CONTAINER, &cas->child, 0,
2189 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2190 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2191 LY_STMT_LEAF, &cas->child, 0,
2192 LY_STMT_LEAF_LIST, &cas->child, 0,
2193 LY_STMT_LIST, &cas->child, 0,
2194 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2195 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2196 LY_STMT_USES, &cas->child, 0,
2197 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2198 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002199 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002200 ret = yin_parse_content(ctx, subelems, 14, LY_STMT_CASE, NULL, &cas->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002201 subelems_deallocator(14, subelems);
2202
2203 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002204}
2205
2206/**
David Sedlák05404f62019-07-24 14:11:53 +02002207 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002208 *
2209 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002210 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002211 *
2212 * @return LY_ERR values.
2213 */
2214LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002215yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002216{
David Sedlák81497a32019-08-13 16:56:26 +02002217 LY_ERR ret = LY_SUCCESS;
2218 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002219 struct lysp_node_choice *choice;
2220
2221 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002222 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002223
David Sedlákb7abcfa2019-07-24 12:33:35 +02002224 choice->nodetype = LYS_CHOICE;
2225 choice->parent = node_meta->parent;
2226
David Sedlákb7abcfa2019-07-24 12:33:35 +02002227 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002228 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2229 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 +02002230
2231 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002232 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002233 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2234 LY_STMT_ANYXML, &choice->child, 0,
2235 LY_STMT_CASE, &choice->child, 0,
2236 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2237 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2238 LY_STMT_CONTAINER, &choice->child, 0,
2239 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2240 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2241 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2242 LY_STMT_LEAF, &choice->child, 0,
2243 LY_STMT_LEAF_LIST, &choice->child, 0,
2244 LY_STMT_LIST, &choice->child, 0,
2245 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2246 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2247 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2248 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2249 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002250 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002251 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_CHOICE, NULL, &choice->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002252 subelems_deallocator(17, subelems);
2253 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002254}
2255
2256/**
David Sedlák05404f62019-07-24 14:11:53 +02002257 * @brief Parse input or output element.
2258 *
2259 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002260 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002261 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2262 *
2263 * @return LY_ERR values.
2264 */
2265static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002266yin_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 +02002267{
David Sedlák81497a32019-08-13 16:56:26 +02002268 LY_ERR ret = LY_SUCCESS;
2269 struct yin_subelement *subelems = NULL;
2270
David Sedlák05404f62019-07-24 14:11:53 +02002271 /* initiate structure */
Radek Krejcid6b76452019-09-03 17:03:03 +02002272 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002273 inout_meta->inout_p->parent = inout_meta->parent;
2274
2275 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002276 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2277 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 +02002278
2279 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002280 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002281 LY_STMT_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2282 LY_STMT_ANYXML, &inout_meta->inout_p->data, 0,
2283 LY_STMT_CHOICE, &inout_meta->inout_p->data, 0,
2284 LY_STMT_CONTAINER, &inout_meta->inout_p->data, 0,
2285 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2286 LY_STMT_LEAF, &inout_meta->inout_p->data, 0,
2287 LY_STMT_LEAF_LIST, &inout_meta->inout_p->data, 0,
2288 LY_STMT_LIST, &inout_meta->inout_p->data, 0,
2289 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2290 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2291 LY_STMT_USES, &inout_meta->inout_p->data, 0,
2292 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002293 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002294 ret = yin_parse_content(ctx, subelems, 12, inout_kw, NULL, &inout_meta->inout_p->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002295 subelems_deallocator(12, subelems);
2296 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002297
Michal Vaskob83af8a2020-01-06 09:49:22 +01002298 if (!inout_meta->inout_p->data) {
2299 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2300 return LY_EVALID;
2301 }
2302
David Sedlák05404f62019-07-24 14:11:53 +02002303 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002304 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 +02002305
2306 return LY_SUCCESS;
2307}
2308
David Sedlák992fb7c2019-07-24 16:51:01 +02002309/**
2310 * @brief Parse action element.
2311 *
2312 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002313 * @param[in] act_meta Meta information about parent node and actions to add to.
2314 *
2315 * @return LY_ERR values.
2316 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002317static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002318yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002319{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002320 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002321 LY_ERR ret = LY_SUCCESS;
2322 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002323
2324 /* create new action */
Michal Vaskob36053d2020-03-26 15:49:30 +01002325 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *acts, act, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002326 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002327 act->parent = act_meta->parent;
2328
2329 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002330 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2331 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 +02002332
2333 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002334 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002335 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2336 LY_STMT_GROUPING, &act->groupings, 0,
2337 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2338 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2339 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2340 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2341 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2342 LY_STMT_TYPEDEF, &act->typedefs, 0,
2343 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002344 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002345 ret = (yin_parse_content(ctx, subelems, 9, LY_STMT_ACTION, NULL, &act->exts));
David Sedlák81497a32019-08-13 16:56:26 +02002346 subelems_deallocator(9, subelems);
2347 LY_CHECK_RET(ret);
2348
David Sedlák85d0eca2019-07-24 15:15:21 +02002349 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2350
2351 return LY_SUCCESS;
2352}
2353
David Sedlák05404f62019-07-24 14:11:53 +02002354/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002355 * @brief Parse augment element.
2356 *
2357 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002358 * @param[in] aug_meta Meta information about parent node and augments to add to.
2359 *
2360 * @return LY_ERR values.
2361 */
2362static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002363yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002364{
2365 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002366 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002367 LY_ERR ret = LY_SUCCESS;
2368 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002369
2370 /* create new augment */
Michal Vaskob36053d2020-03-26 15:49:30 +01002371 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002372 aug->nodetype = LYS_AUGMENT;
2373 aug->parent = aug_meta->parent;
2374
2375 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002376 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2377 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2378 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002379
2380 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002381 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002382 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2383 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2384 LY_STMT_ANYXML, &aug->child, 0,
2385 LY_STMT_CASE, &aug->child, 0,
2386 LY_STMT_CHOICE, &aug->child, 0,
2387 LY_STMT_CONTAINER, &aug->child, 0,
2388 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2389 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
2390 LY_STMT_LEAF, &aug->child, 0,
2391 LY_STMT_LEAF_LIST, &aug->child, 0,
2392 LY_STMT_LIST, &aug->child, 0,
2393 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2394 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2395 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2396 LY_STMT_USES, &aug->child, 0,
2397 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2398 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002399 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002400 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_AUGMENT, NULL, &aug->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002401 subelems_deallocator(17, subelems);
2402 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002403
2404 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2405
2406 return LY_SUCCESS;
2407}
2408
David Sedlák8b754462019-07-25 16:22:13 +02002409/**
2410 * @brief Parse deviate element.
2411 *
2412 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002413 * @param[in] deviates Deviates to add to.
2414 *
2415 * @return LY_ERR values.
2416 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002417static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002418yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002419{
2420 LY_ERR ret = LY_SUCCESS;
2421 uint8_t dev_mod;
2422 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002423 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002424 struct lysp_deviate_add *d_add = NULL;
2425 struct lysp_deviate_rpl *d_rpl = NULL;
2426 struct lysp_deviate_del *d_del = NULL;
2427
2428 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002429 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2430 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 +02002431
2432 if (strcmp(temp_val, "not-supported") == 0) {
2433 dev_mod = LYS_DEV_NOT_SUPPORTED;
2434 } else if (strcmp(temp_val, "add") == 0) {
2435 dev_mod = LYS_DEV_ADD;
2436 } else if (strcmp(temp_val, "replace") == 0) {
2437 dev_mod = LYS_DEV_REPLACE;
2438 } else if (strcmp(temp_val, "delete") == 0) {
2439 dev_mod = LYS_DEV_DELETE;
2440 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002441 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
2442 "not-supported", "add", "replace", "delete");
Michal Vaskob36053d2020-03-26 15:49:30 +01002443 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002444 return LY_EVALID;
2445 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002446 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002447
2448 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2449 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002450 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002451 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002452 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák4ffcec82019-07-25 15:10:21 +02002453 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002454 ret = yin_parse_content(ctx, subelems, 1, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002455
2456 } else if (dev_mod == LYS_DEV_ADD) {
2457 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002458 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002459 d = (struct lysp_deviate *)d_add;
2460 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2461 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2462 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002463 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2464 {LY_STMT_DEFAULT, &d_add->dflts, 0},
2465 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2466 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2467 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2468 {LY_STMT_MUST, &d_add->musts, 0},
2469 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2470 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2471 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002472 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002473 ret = yin_parse_content(ctx, subelems, 9, LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002474
2475 } else if (dev_mod == LYS_DEV_REPLACE) {
2476 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002477 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002478 d = (struct lysp_deviate *)d_rpl;
2479 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2480 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2481 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002482 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2483 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2484 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2485 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2486 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2487 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2488 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2489 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002490 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002491 ret = yin_parse_content(ctx, subelems, 8, LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002492
2493 } else {
2494 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002495 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002496 d = (struct lysp_deviate *)d_del;
2497 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002498 {LY_STMT_DEFAULT, &d_del->dflts, 0},
2499 {LY_STMT_MUST, &d_del->musts, 0},
2500 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2501 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2502 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002503 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002504 ret = yin_parse_content(ctx, subelems, 5, LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002505 }
2506 LY_CHECK_GOTO(ret, cleanup);
2507
2508 d->mod = dev_mod;
2509 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002510 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002511
2512 return ret;
2513
2514cleanup:
2515 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002516 return ret;
2517}
2518
David Sedlák992fb7c2019-07-24 16:51:01 +02002519/**
David Sedlák8b754462019-07-25 16:22:13 +02002520 * @brief Parse deviation element.
2521 *
2522 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002523 * @param[in] deviations Deviations to add to.
2524 *
2525 * @return LY_ERR values.
2526 */
2527static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002528yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002529{
2530 struct lysp_deviation *dev;
2531
2532 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002533 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002534
2535 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002536 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2537 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2538 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
David Sedlák8b754462019-07-25 16:22:13 +02002539 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002540 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2541 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2542 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2543 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8b754462019-07-25 16:22:13 +02002544 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002545 return yin_parse_content(ctx, subelems, 4, LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002546}
2547
2548/**
David Sedlákb4e44562019-07-04 15:42:12 +02002549 * @brief Map keyword type to substatement info.
2550 *
2551 * @param[in] kw Keyword type.
2552 *
2553 * @return correct LYEXT_SUBSTMT information.
2554 */
2555static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002556kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002557{
2558 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002559 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002560 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002561 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002562 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002563 case LY_STMT_BELONGS_TO:
David Sedlákb4e44562019-07-04 15:42:12 +02002564 return LYEXT_SUBSTMT_BELONGSTO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002565 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002566 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002567 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002568 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002569 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002570 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002571 case LY_STMT_ERROR_APP_TAG:
David Sedlákb4e44562019-07-04 15:42:12 +02002572 return LYEXT_SUBSTMT_ERRTAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002573 case LY_STMT_ERROR_MESSAGE:
David Sedlákb4e44562019-07-04 15:42:12 +02002574 return LYEXT_SUBSTMT_ERRMSG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002575 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002576 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002577 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002578 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002579 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002580 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002581 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002582 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002583 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002584 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002585 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002586 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002587 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002588 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002589 case LY_STMT_REVISION_DATE:
David Sedlákb4e44562019-07-04 15:42:12 +02002590 return LYEXT_SUBSTMT_REVISIONDATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002591 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002592 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002593 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002594 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002595 case LY_STMT_YANG_VERSION:
David Sedlákb4e44562019-07-04 15:42:12 +02002596 return LYEXT_SUBSTMT_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002597 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002598 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002599 case LY_STMT_REQUIRE_INSTANCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002600 return LYEXT_SUBSTMT_REQINSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002601 case LY_STMT_YIN_ELEMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002602 return LYEXT_SUBSTMT_YINELEM;
Radek Krejcid6b76452019-09-03 17:03:03 +02002603 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002604 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002605 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002606 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002607 case LY_STMT_ORDERED_BY:
David Sedlákb4e44562019-07-04 15:42:12 +02002608 return LYEXT_SUBSTMT_ORDEREDBY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002609 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002610 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002611 case LY_STMT_FRACTION_DIGITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002612 return LYEXT_SUBSTMT_FRACDIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002613 case LY_STMT_MAX_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002614 return LYEXT_SUBSTMT_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002615 case LY_STMT_MIN_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002616 return LYEXT_SUBSTMT_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02002617 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002618 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002619 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002620 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002621 case LY_STMT_IF_FEATURE:
David Sedlákb4e44562019-07-04 15:42:12 +02002622 return LYEXT_SUBSTMT_IFFEATURE;
2623 default:
2624 return LYEXT_SUBSTMT_SELF;
2625 }
2626}
2627
David Sedlákc5b20842019-08-13 10:18:31 +02002628/**
2629 * @brief map keyword to keyword-group.
2630 *
2631 * @param[in] ctx YIN parser context used for logging.
2632 * @param[in] kw Keyword that is child of module or submodule.
2633 * @param[out] group Group of keyword.
2634 *
2635 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2636 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002637static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002638kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002639{
2640 switch (kw) {
2641 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02002642 case LY_STMT_NONE:
2643 case LY_STMT_NAMESPACE:
2644 case LY_STMT_PREFIX:
2645 case LY_STMT_BELONGS_TO:
2646 case LY_STMT_YANG_VERSION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002647 *group = Y_MOD_MODULE_HEADER;
2648 break;
2649 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02002650 case LY_STMT_INCLUDE:
2651 case LY_STMT_IMPORT:
David Sedláke6cd89e2019-08-07 12:46:02 +02002652 *group = Y_MOD_LINKAGE;
2653 break;
2654 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02002655 case LY_STMT_ORGANIZATION:
2656 case LY_STMT_CONTACT:
2657 case LY_STMT_DESCRIPTION:
2658 case LY_STMT_REFERENCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002659 *group = Y_MOD_META;
2660 break;
2661 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02002662 case LY_STMT_REVISION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002663 *group = Y_MOD_REVISION;
2664 break;
2665 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02002666 case LY_STMT_ANYDATA:
2667 case LY_STMT_ANYXML:
2668 case LY_STMT_AUGMENT:
2669 case LY_STMT_CHOICE:
2670 case LY_STMT_CONTAINER:
2671 case LY_STMT_DEVIATION:
2672 case LY_STMT_EXTENSION:
2673 case LY_STMT_FEATURE:
2674 case LY_STMT_GROUPING:
2675 case LY_STMT_IDENTITY:
2676 case LY_STMT_LEAF:
2677 case LY_STMT_LEAF_LIST:
2678 case LY_STMT_LIST:
2679 case LY_STMT_NOTIFICATION:
2680 case LY_STMT_RPC:
2681 case LY_STMT_TYPEDEF:
2682 case LY_STMT_USES:
2683 case LY_STMT_EXTENSION_INSTANCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002684 *group = Y_MOD_BODY;
2685 break;
2686 default:
Michal Vaskob36053d2020-03-26 15:49:30 +01002687 LOGINT(ctx->xmlctx->ctx);
David Sedláke6cd89e2019-08-07 12:46:02 +02002688 return LY_EINT;
2689 }
2690
2691 return LY_SUCCESS;
2692}
2693
David Sedlákc5b20842019-08-13 10:18:31 +02002694/**
2695 * @brief Check if relative order of two keywords is valid.
2696 *
2697 * @param[in] ctx YIN parser context used for logging.
2698 * @param[in] kw Current keyword.
2699 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002700 * @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 +02002701 * because relative order is required only in module and submodule sub-elements, used for logging.
2702 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002703 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002704 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002705static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002706yin_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 +02002707{
Radek Krejcid6b76452019-09-03 17:03:03 +02002708 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002709 enum yang_module_stmt gr, next_gr;
2710
2711 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2712 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2713
2714 if (gr > next_gr) {
2715 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2716 return LY_EVALID;
2717 }
2718
2719 return LY_SUCCESS;
2720}
2721
David Sedlákc5dd0942019-09-13 10:23:59 +02002722/**
2723 * @brief Get element name prefixed by full URI of xml namespace.
2724 *
2725 * @param[in] ctx YIN parser context used for logging and to get inormation about xml namespaces.
2726 * @param[in] name Name of element.
2727 * @param[in] name_len Length of element name.
2728 * @param[in] prefix Prefix of element.
2729 * @param[in] prefix_len Length of element prefix.
2730 *
2731 * @return Element name prefixed by URI on success, NULL on failure.
2732 */
2733static const char *
Michal Vaskob36053d2020-03-26 15:49:30 +01002734name2nsname(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 +02002735{
Michal Vaskob36053d2020-03-26 15:49:30 +01002736 const struct lyxml_ns *ns = lyxml_ns_get(ctx->xmlctx, prefix, prefix_len);
2737 LY_CHECK_ERR_RET(!ns, LOGINT(ctx->xmlctx->ctx), NULL);
David Sedlák068dd352019-09-13 09:08:22 +02002738
Radek Krejci02728562019-09-18 14:13:05 +02002739 if (!strcmp(ns->uri, YIN_NS_URI)) {
2740 /* standard YANG statement in YIN namespace - keep it unprefixed as in case of YANG */
Michal Vaskob36053d2020-03-26 15:49:30 +01002741 return lydict_insert(ctx->xmlctx->ctx, name, name_len);
Radek Krejci02728562019-09-18 14:13:05 +02002742 }
2743 /* some statement in special namespace (extension instance) */
David Sedláke0ef1c62019-09-13 10:05:55 +02002744 size_t ns_len = strlen(ns->uri);
2745 size_t len = ns_len + name_len + 1; /* +1 because of ':' delimiter between ns and actual name */
2746
2747 char *result;
2748 char *temp;
2749 temp = result = malloc(sizeof(*temp) * (len + 1)); /* +1 for '\0' terminator */
Michal Vaskob36053d2020-03-26 15:49:30 +01002750 LY_CHECK_ERR_RET(!temp, LOGMEM(ctx->xmlctx->ctx), NULL);
David Sedláke0ef1c62019-09-13 10:05:55 +02002751
2752 strcpy(result, ns->uri);
2753 result[ns_len] = ':';
2754 temp = &result[ns_len + 1];
2755 strncpy(temp, name, name_len);
2756 result[len] = '\0';
2757
Michal Vaskob36053d2020-03-26 15:49:30 +01002758 return lydict_insert_zc(ctx->xmlctx->ctx, result);
David Sedlák068dd352019-09-13 09:08:22 +02002759}
2760
David Sedlákd6e56892019-07-01 15:40:24 +02002761LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002762yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
2763 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02002764{
2765 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01002766 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02002767 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002768 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002769
Michal Vaskob36053d2020-03-26 15:49:30 +01002770 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02002771
Michal Vaskob36053d2020-03-26 15:49:30 +01002772 if (ctx->xmlctx->ws_only) {
2773 /* check whether there are any children */
2774 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
2775 } else {
2776 /* we want to parse the value */
2777 next_status = LYXML_ELEM_CLOSE;
2778 }
2779
2780 if (next_status == LYXML_ELEMENT) {
2781 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
2782
2783 /* current element has subelements as content */
2784 while (ctx->xmlctx->status == LYXML_ELEMENT) {
2785 /* match keyword */
2786 last_kw = kw;
2787 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
2788 ctx->xmlctx->prefix_len, current_element);
2789
2790 /* check if this element can be child of current element */
2791 subelem = get_record(kw, subelem_info_size, subelem_info);
2792 if (!subelem) {
2793 if (current_element == LY_STMT_DEVIATE && isdevsub(kw)) {
2794 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2795 } else {
2796 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
2797 ctx->xmlctx->name, ly_stmt2str(current_element));
2798 }
2799 ret = LY_EVALID;
2800 goto cleanup;
2801 }
2802
2803 /* relative order is required only in module and submodule sub-elements */
2804 if (current_element == LY_STMT_MODULE || current_element == LY_STMT_SUBMODULE) {
2805 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2806 LY_CHECK_GOTO(ret, cleanup);
2807 }
2808
2809 /* flag check */
2810 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
2811 /* subelement uniquenes */
2812 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
2813 return LY_EVALID;
2814 }
2815 if (subelem->flags & YIN_SUBELEM_FIRST) {
2816 /* subelement is supposed to be defined as first subelement */
2817 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
2818 LY_CHECK_GOTO(ret, cleanup);
2819 }
2820 if (subelem->flags & YIN_SUBELEM_VER2) {
2821 /* subelement is supported only in version 1.1 or higher */
2822 if (ctx->mod_version < 2) {
2823 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 +02002824 ret = LY_EVALID;
2825 goto cleanup;
2826 }
David Sedlákd6e56892019-07-01 15:40:24 +02002827 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002828 /* note that element was parsed for easy uniqueness check in next iterations */
2829 subelem->flags |= YIN_SUBELEM_PARSED;
2830
2831 switch (kw) {
2832 /* call responsible function */
2833 case LY_STMT_EXTENSION_INSTANCE:
2834 ret = yin_parse_extension_instance(ctx, kw2lyext_substmt(current_element),
Radek Krejci7eb54ba2020-05-18 16:30:04 +02002835 (subelem->dest) ? *((LY_ARRAY_SIZE_TYPE*)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01002836 break;
2837 case LY_STMT_ACTION:
2838 case LY_STMT_RPC:
2839 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
2840 break;
2841 case LY_STMT_ANYDATA:
2842 case LY_STMT_ANYXML:
2843 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
2844 break;
2845 case LY_STMT_ARGUMENT:
2846 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
2847 break;
2848 case LY_STMT_AUGMENT:
2849 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
2850 break;
2851 case LY_STMT_BASE:
2852 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
2853 break;
2854 case LY_STMT_BELONGS_TO:
2855 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
2856 break;
2857 case LY_STMT_BIT:
2858 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
2859 break;
2860 case LY_STMT_CASE:
2861 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
2862 break;
2863 case LY_STMT_CHOICE:
2864 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
2865 break;
2866 case LY_STMT_CONFIG:
2867 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
2868 break;
2869 case LY_STMT_CONTACT:
2870 case LY_STMT_DESCRIPTION:
2871 case LY_STMT_ORGANIZATION:
2872 case LY_STMT_REFERENCE:
2873 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
2874 break;
2875 case LY_STMT_CONTAINER:
2876 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
2877 break;
2878 case LY_STMT_DEFAULT:
2879 case LY_STMT_ERROR_APP_TAG:
2880 case LY_STMT_KEY:
2881 case LY_STMT_PRESENCE:
2882 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
2883 break;
2884 case LY_STMT_DEVIATE:
2885 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
2886 break;
2887 case LY_STMT_DEVIATION:
2888 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
2889 break;
2890 case LY_STMT_ENUM:
2891 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
2892 break;
2893 case LY_STMT_ERROR_MESSAGE:
2894 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
2895 break;
2896 case LY_STMT_EXTENSION:
2897 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
2898 break;
2899 case LY_STMT_FEATURE:
2900 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
2901 break;
2902 case LY_STMT_FRACTION_DIGITS:
2903 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
2904 break;
2905 case LY_STMT_GROUPING:
2906 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
2907 break;
2908 case LY_STMT_IDENTITY:
2909 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
2910 break;
2911 case LY_STMT_IF_FEATURE:
2912 case LY_STMT_UNITS:
2913 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
2914 break;
2915 case LY_STMT_IMPORT:
2916 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
2917 break;
2918 case LY_STMT_INCLUDE:
2919 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
2920 break;
2921 case LY_STMT_INPUT:
2922 case LY_STMT_OUTPUT:
2923 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
2924 break;
2925 case LY_STMT_LEAF:
2926 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
2927 break;
2928 case LY_STMT_LEAF_LIST:
2929 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
2930 break;
2931 case LY_STMT_LENGTH:
2932 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
2933 break;
2934 case LY_STMT_LIST:
2935 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
2936 break;
2937 case LY_STMT_MANDATORY:
2938 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
2939 break;
2940 case LY_STMT_MAX_ELEMENTS:
2941 case LY_STMT_MIN_ELEMENTS:
2942 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
2943 break;
2944 case LY_STMT_MODIFIER:
2945 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
2946 break;
2947 case LY_STMT_MUST:
2948 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
2949 break;
2950 case LY_STMT_NAMESPACE:
2951 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
2952 break;
2953 case LY_STMT_NOTIFICATION:
2954 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
2955 break;
2956 case LY_STMT_ORDERED_BY:
2957 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
2958 break;
2959 case LY_STMT_PATH:
2960 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
2961 break;
2962 case LY_STMT_PATTERN:
2963 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
2964 break;
2965 case LY_STMT_VALUE:
2966 case LY_STMT_POSITION:
2967 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
2968 break;
2969 case LY_STMT_PREFIX:
2970 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
2971 break;
2972 case LY_STMT_RANGE:
2973 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
2974 break;
2975 case LY_STMT_REFINE:
2976 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
2977 break;
2978 case LY_STMT_REQUIRE_INSTANCE:
2979 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
2980 break;
2981 case LY_STMT_REVISION:
2982 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
2983 break;
2984 case LY_STMT_REVISION_DATE:
2985 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
2986 break;
2987 case LY_STMT_STATUS:
2988 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
2989 break;
2990 case LY_STMT_TYPE:
2991 ret = yin_parse_type(ctx, current_element, subelem);
2992 break;
2993 case LY_STMT_TYPEDEF:
2994 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
2995 break;
2996 case LY_STMT_UNIQUE:
2997 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
2998 break;
2999 case LY_STMT_USES:
3000 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3001 break;
3002 case LY_STMT_WHEN:
3003 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3004 break;
3005 case LY_STMT_YANG_VERSION:
3006 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3007 break;
3008 case LY_STMT_YIN_ELEMENT:
3009 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3010 break;
3011 case LY_STMT_ARG_TEXT:
3012 case LY_STMT_ARG_VALUE:
3013 /* TODO what to do with content/attributes? */
3014 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3015 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3016 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3017 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3018 }
3019 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3020 break;
3021 default:
3022 LOGINT(ctx->xmlctx->ctx);
3023 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003024 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003025 LY_CHECK_GOTO(ret, cleanup);
3026 subelem = NULL;
3027
3028 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003029 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003030 } else {
3031 LY_CHECK_RET(ret);
3032 /* elements with text or none content */
3033 /* save text content, if text_content isn't set, it's just ignored */
3034 /* no resources are allocated in this branch, no need to use cleanup label */
3035 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3036 if (text_content) {
3037 *text_content = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3038 LY_CHECK_RET(!*text_content, LY_EMEM);
3039 }
3040
3041 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003042 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003043
David Sedlák8b754462019-07-25 16:22:13 +02003044 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3045 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003046
3047cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003048 return ret;
3049}
3050
David Sedlák619db942019-07-03 14:47:30 +02003051LY_ERR
Radek Krejci7eb54ba2020-05-18 16:30:04 +02003052yin_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 +01003053 struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003054{
David Sedlák1e2cdd02019-06-27 14:17:43 +02003055 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003056 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003057
Michal Vaskob36053d2020-03-26 15:49:30 +01003058 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3059
3060 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003061
3062 e->yin = 0;
3063 /* store name and insubstmt info */
Michal Vaskob36053d2020-03-26 15:49:30 +01003064 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 +02003065 LY_CHECK_RET(!e->name, LY_EMEM);
David Sedlák619db942019-07-03 14:47:30 +02003066 e->insubstmt = subelem;
3067 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003068 e->yin |= LYS_YIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01003069 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003070
David Sedlákb1a78352019-06-28 16:16:29 +02003071 /* store attributes as subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003072 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3073 if (!ctx->xmlctx->prefix) {
David Sedlákb1a78352019-06-28 16:16:29 +02003074 new_subelem = calloc(1, sizeof(*new_subelem));
3075 if (!e->child) {
3076 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003077 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003078 last_subelem->next = new_subelem;
3079 }
3080 last_subelem = new_subelem;
3081
3082 last_subelem->flags |= LYS_YIN_ATTR;
Michal Vaskob36053d2020-03-26 15:49:30 +01003083 last_subelem->stmt = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák169cc522019-08-15 13:23:45 +02003084 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003085 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák169cc522019-08-15 13:23:45 +02003086
Michal Vaskob36053d2020-03-26 15:49:30 +01003087 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 +02003088 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003089 } else {
3090 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003091 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003092
3093 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003094 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003095
David Sedlákf250ecf2019-07-01 11:02:05 +02003096 /* parse subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003097 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3098 if (ctx->xmlctx->ws_only) {
3099 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3100 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3101 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3102 if (!e->child) {
3103 e->child = new_subelem;
3104 } else {
3105 last_subelem->next = new_subelem;
David Sedlákb1a78352019-06-28 16:16:29 +02003106 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003107 last_subelem = new_subelem;
David Sedlák169cc522019-08-15 13:23:45 +02003108
Michal Vaskob36053d2020-03-26 15:49:30 +01003109 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3110 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003111 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003112 } else if (ctx->xmlctx->value_len) {
3113 /* save text content */
3114 e->argument = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3115 LY_CHECK_RET(!e->argument, LY_EMEM);
3116
3117 /* parser next */
3118 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003119 }
3120
3121 return LY_SUCCESS;
3122}
3123
David Sedlákaa98bba2019-09-12 11:52:14 +02003124/**
3125 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
3126 *
3127 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákaa98bba2019-09-12 11:52:14 +02003128 * @param[in] elem_type Type of element that is currently being parsed.
3129 * @param[out] arg Value to write to.
3130 *
3131 * @return LY_ERR values.
3132 */
3133static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003134yin_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 +02003135{
David Sedlák071f7662019-09-12 02:02:51 +02003136 enum ly_stmt child;
David Sedláke6284fc2019-09-10 11:57:02 +02003137
Michal Vaskob36053d2020-03-26 15:49:30 +01003138 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3139
David Sedláke6284fc2019-09-10 11:57:02 +02003140 switch (elem_type) {
3141 case LY_STMT_ACTION:
3142 case LY_STMT_ANYDATA:
3143 case LY_STMT_ANYXML:
3144 case LY_STMT_ARGUMENT:
3145 case LY_STMT_BASE:
3146 case LY_STMT_BIT:
3147 case LY_STMT_CASE:
3148 case LY_STMT_CHOICE:
3149 case LY_STMT_CONTAINER:
3150 case LY_STMT_ENUM:
3151 case LY_STMT_EXTENSION:
3152 case LY_STMT_FEATURE:
3153 case LY_STMT_GROUPING:
3154 case LY_STMT_IDENTITY:
3155 case LY_STMT_IF_FEATURE:
3156 case LY_STMT_LEAF:
3157 case LY_STMT_LEAF_LIST:
3158 case LY_STMT_LIST:
3159 case LY_STMT_MODULE:
3160 case LY_STMT_NOTIFICATION:
3161 case LY_STMT_RPC:
3162 case LY_STMT_SUBMODULE:
3163 case LY_STMT_TYPE:
3164 case LY_STMT_TYPEDEF:
3165 case LY_STMT_UNITS:
3166 case LY_STMT_USES:
Michal Vaskob36053d2020-03-26 15:49:30 +01003167 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 +02003168 break;
3169 case LY_STMT_AUGMENT:
3170 case LY_STMT_DEVIATION:
3171 case LY_STMT_REFINE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003172 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 +02003173 break;
3174 case LY_STMT_CONFIG:
3175 case LY_STMT_DEFAULT:
3176 case LY_STMT_DEVIATE:
3177 case LY_STMT_ERROR_APP_TAG:
David Sedláke6284fc2019-09-10 11:57:02 +02003178 case LY_STMT_FRACTION_DIGITS:
3179 case LY_STMT_KEY:
3180 case LY_STMT_LENGTH:
3181 case LY_STMT_MANDATORY:
3182 case LY_STMT_MAX_ELEMENTS:
3183 case LY_STMT_MIN_ELEMENTS:
3184 case LY_STMT_MODIFIER:
3185 case LY_STMT_ORDERED_BY:
3186 case LY_STMT_PATH:
3187 case LY_STMT_PATTERN:
3188 case LY_STMT_POSITION:
3189 case LY_STMT_PREFIX:
3190 case LY_STMT_PRESENCE:
3191 case LY_STMT_RANGE:
3192 case LY_STMT_REQUIRE_INSTANCE:
3193 case LY_STMT_STATUS:
3194 case LY_STMT_VALUE:
3195 case LY_STMT_YANG_VERSION:
3196 case LY_STMT_YIN_ELEMENT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003197 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 +02003198 break;
3199 case LY_STMT_IMPORT:
3200 case LY_STMT_INCLUDE:
3201 case LY_STMT_BELONGS_TO:
Michal Vaskob36053d2020-03-26 15:49:30 +01003202 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 +02003203 break;
3204 case LY_STMT_INPUT:
3205 case LY_STMT_OUTPUT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003206 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 +02003207 break;
3208 case LY_STMT_MUST:
3209 case LY_STMT_WHEN:
Michal Vaskob36053d2020-03-26 15:49:30 +01003210 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 +02003211 break;
3212 case LY_STMT_NAMESPACE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003213 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 +02003214 break;
3215 case LY_STMT_REVISION:
3216 case LY_STMT_REVISION_DATE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003217 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 +02003218 break;
3219 case LY_STMT_UNIQUE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003220 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 +02003221 break;
David Sedlák071f7662019-09-12 02:02:51 +02003222 /* argument is mapped to yin element */
3223 case LY_STMT_CONTACT:
3224 case LY_STMT_DESCRIPTION:
3225 case LY_STMT_ORGANIZATION:
3226 case LY_STMT_REFERENCE:
3227 case LY_STMT_ERROR_MESSAGE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003228 /* there shouldn't be any attribute, argument is supposed to be first subelement */
Michal Vaskob36053d2020-03-26 15:49:30 +01003229 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3230
3231 /* no content */
3232 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3233 if (ctx->xmlctx->ws_only) {
3234 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3235 }
3236 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3237 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
3238 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
David Sedlák071f7662019-09-12 02:02:51 +02003239 return LY_EVALID;
3240 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003241
3242 /* parse child element */
3243 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
3244 if ((elem_type == LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_VALUE) ||
3245 (elem_type != LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_TEXT)) {
3246 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3247 ly_stmt2str(elem_type));
3248 return LY_EVALID;
David Sedlákaa98bba2019-09-12 11:52:14 +02003249 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003250 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3251
3252 /* no attributes expected? TODO */
3253 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3254 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3255 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3256 }
3257
3258 /* load and save content */
3259 *arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3260 LY_CHECK_RET(!*arg, LY_EMEM);
3261
3262 /* load closing tag of subelement */
3263 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3264
3265 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3266 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3267 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3268 }*/
David Sedlákb0ca07d2019-09-11 11:54:05 +02003269 break;
David Sedláke6284fc2019-09-10 11:57:02 +02003270 default:
Michal Vaskob36053d2020-03-26 15:49:30 +01003271 LOGINT(ctx->xmlctx->ctx);
David Sedlák071f7662019-09-12 02:02:51 +02003272 return LY_EINT;
David Sedláke6284fc2019-09-10 11:57:02 +02003273 }
3274
David Sedlák071f7662019-09-12 02:02:51 +02003275 return LY_SUCCESS;
David Sedláke6284fc2019-09-10 11:57:02 +02003276}
3277
3278LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003279yin_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 +02003280{
3281 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003282 struct lysp_stmt *last = NULL, *new = NULL;
3283
Michal Vaskob36053d2020-03-26 15:49:30 +01003284 assert(ctx->xmlctx->status == LYXML_ELEMENT);
David Sedláke0ef1c62019-09-13 10:05:55 +02003285
3286 /* allocate new structure for element */
3287 *element = calloc(1, sizeof(**element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003288 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3289 (*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 +02003290 LY_CHECK_ERR_GOTO(!(*element)->stmt, ret = LY_EMEM, cleanup);
David Sedláke0ef1c62019-09-13 10:05:55 +02003291
Michal Vaskob36053d2020-03-26 15:49:30 +01003292 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3293 ctx->xmlctx->prefix_len, parent);
David Sedlákb1a78352019-06-28 16:16:29 +02003294
3295 last = (*element)->child;
David Sedláke6284fc2019-09-10 11:57:02 +02003296 if ((*element)->kw == LY_STMT_NONE) {
3297 /* unrecognized element */
Michal Vaskob36053d2020-03-26 15:49:30 +01003298 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3299 ly_stmt2str(parent));
David Sedlákaa98bba2019-09-12 11:52:14 +02003300 ret = LY_EVALID;
3301 goto cleanup;
David Sedláke6284fc2019-09-10 11:57:02 +02003302 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3303 /* element is known yang keyword, which means argument can be parsed correctly. */
Michal Vaskob36053d2020-03-26 15:49:30 +01003304 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
David Sedlákaa98bba2019-09-12 11:52:14 +02003305 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003306 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01003307 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3308
David Sedlákaa98bba2019-09-12 11:52:14 +02003309 /* load attributes in generic way, save all attributes in linked list */
Michal Vaskob36053d2020-03-26 15:49:30 +01003310 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedláke6284fc2019-09-10 11:57:02 +02003311 new = calloc(1, sizeof(*last));
Michal Vaskob36053d2020-03-26 15:49:30 +01003312 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003313 if (!(*element)->child) {
3314 /* save first */
3315 (*element)->child = new;
3316 } else {
3317 last->next = new;
3318 }
3319 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003320
David Sedláke6284fc2019-09-10 11:57:02 +02003321 last->flags |= LYS_YIN_ATTR;
Michal Vaskob36053d2020-03-26 15:49:30 +01003322 last->stmt = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlákb0ca07d2019-09-11 11:54:05 +02003323 last->kw = LY_STMT_NONE;
David Sedláke6284fc2019-09-10 11:57:02 +02003324 /* attributes with prefix are ignored */
Michal Vaskob36053d2020-03-26 15:49:30 +01003325 if (!ctx->xmlctx->prefix) {
3326 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3327
3328 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 +02003329 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003330 } else {
3331 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003332 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003333 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003334 }
3335 }
3336
Michal Vaskob36053d2020-03-26 15:49:30 +01003337 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3338 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3339 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3340 /* parse subelements */
3341 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
David Sedlákaa98bba2019-09-12 11:52:14 +02003342 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003343 if (!(*element)->child) {
3344 /* save first */
3345 (*element)->child = new;
3346 } else {
3347 last->next = new;
David Sedláka82ecff2019-08-16 10:51:48 +02003348 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003349 last = new;
David Sedlák169cc522019-08-15 13:23:45 +02003350
Michal Vaskob36053d2020-03-26 15:49:30 +01003351 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3352 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003353 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003354 } else {
3355 /* save element content */
3356 if (ctx->xmlctx->value_len) {
3357 (*element)->arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3358 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
3359 }
3360
3361 /* read closing tag */
3362 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003363 }
3364
David Sedlákb0ca07d2019-09-11 11:54:05 +02003365cleanup:
David Sedlákb0ca07d2019-09-11 11:54:05 +02003366 return ret;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003367}
3368
3369LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003370yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003371{
David Sedlák81497a32019-08-13 16:56:26 +02003372 LY_ERR ret = LY_SUCCESS;
3373 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003374 struct lysp_submodule *dup;
David Sedlák3b4db242018-10-19 16:11:01 +02003375
Michal Vaskob36053d2020-03-26 15:49:30 +01003376 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3377 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 +02003378 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003379 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3380 LY_STMT_ANYXML, &mod->data, 0,
3381 LY_STMT_AUGMENT, &mod->augments, 0,
3382 LY_STMT_CHOICE, &mod->data, 0,
3383 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3384 LY_STMT_CONTAINER, &mod->data, 0,
3385 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3386 LY_STMT_DEVIATION, &mod->deviations, 0,
3387 LY_STMT_EXTENSION, &mod->extensions, 0,
3388 LY_STMT_FEATURE, &mod->features, 0,
3389 LY_STMT_GROUPING, &mod->groupings, 0,
3390 LY_STMT_IDENTITY, &mod->identities, 0,
3391 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3392 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3393 LY_STMT_LEAF, &mod->data, 0,
3394 LY_STMT_LEAF_LIST, &mod->data, 0,
3395 LY_STMT_LIST, &mod->data, 0,
3396 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3397 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3398 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3399 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3400 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3401 LY_STMT_REVISION, &mod->revs, 0,
3402 LY_STMT_RPC, &mod->rpcs, 0,
3403 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3404 LY_STMT_USES, &mod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003405 LY_STMT_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003406 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003407 ));
3408
Michal Vaskob36053d2020-03-26 15:49:30 +01003409 ret = yin_parse_content(ctx, subelems, 28, LY_STMT_MODULE, NULL, &mod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003410 subelems_deallocator(28, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003411 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003412
David Sedláked809f12019-09-13 10:15:11 +02003413 /* finalize parent pointers to the reallocated items */
3414 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
3415
3416 /* submodules share the namespace with the module names, so there must not be
3417 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003418 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, mod->mod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003419 if (dup) {
3420 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
3421 return LY_EVALID;
3422 }
3423
3424 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003425}
3426
3427LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003428yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003429{
David Sedlák81497a32019-08-13 16:56:26 +02003430 LY_ERR ret = LY_SUCCESS;
3431 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003432 struct lysp_submodule *dup;
David Sedlák298ff6d2019-07-26 14:29:03 +02003433
Michal Vaskob36053d2020-03-26 15:49:30 +01003434 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3435 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 +02003436 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003437 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3438 LY_STMT_ANYXML, &submod->data, 0,
3439 LY_STMT_AUGMENT, &submod->augments, 0,
3440 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3441 LY_STMT_CHOICE, &submod->data, 0,
3442 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3443 LY_STMT_CONTAINER, &submod->data, 0,
3444 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3445 LY_STMT_DEVIATION, &submod->deviations, 0,
3446 LY_STMT_EXTENSION, &submod->extensions, 0,
3447 LY_STMT_FEATURE, &submod->features, 0,
3448 LY_STMT_GROUPING, &submod->groupings, 0,
3449 LY_STMT_IDENTITY, &submod->identities, 0,
3450 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3451 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3452 LY_STMT_LEAF, &submod->data, 0,
3453 LY_STMT_LEAF_LIST, &submod->data, 0,
3454 LY_STMT_LIST, &submod->data, 0,
3455 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3456 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3457 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3458 LY_STMT_REVISION, &submod->revs, 0,
3459 LY_STMT_RPC, &submod->rpcs, 0,
3460 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3461 LY_STMT_USES, &submod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003462 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003463 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003464 ));
3465
Michal Vaskob36053d2020-03-26 15:49:30 +01003466 ret = yin_parse_content(ctx, subelems, 27, LY_STMT_SUBMODULE, NULL, &submod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003467 subelems_deallocator(27, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003468 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003469
David Sedláked809f12019-09-13 10:15:11 +02003470 /* finalize parent pointers to the reallocated items */
3471 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
3472
3473 /* submodules share the namespace with the module names, so there must not be
3474 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003475 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, submod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003476 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
3477 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
3478 return LY_EVALID;
3479 }
3480
3481 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003482}
3483
3484LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003485yin_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 +02003486{
Radek Krejcid6b76452019-09-03 17:03:03 +02003487 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003488 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003489 struct lysp_submodule *mod_p = NULL;
3490
3491 /* create context */
3492 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003493 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003494 (*yin_ctx)->format = LYS_IN_YIN;
3495 LY_CHECK_RET(lyxml_ctx_new(ctx, data, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003496
David Sedlák1b623122019-08-05 15:27:49 +02003497 /* map the typedefs and groupings list from main context to the submodule's context */
3498 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3499 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3500
David Sedlák8985a142019-07-31 16:43:06 +02003501 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003502 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
3503 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003504 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003505 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3506 ret = LY_EINVAL;
3507 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003508 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003509 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003510 ret = LY_EVALID;
3511 goto cleanup;
3512 }
3513
3514 mod_p = calloc(1, sizeof *mod_p);
3515 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3516 mod_p->parsing = 1;
3517
Michal Vaskob36053d2020-03-26 15:49:30 +01003518 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003519 LY_CHECK_GOTO(ret, cleanup);
3520
David Sedlákbf8a2b72019-08-14 16:48:10 +02003521 /* skip possible trailing whitespaces at end of the input */
Michal Vaskob36053d2020-03-26 15:49:30 +01003522 data = (*yin_ctx)->xmlctx->input;
3523 while (*data && isspace(*data)) {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003524 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003525 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003526 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003527 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 +02003528 ret = LY_EVALID;
3529 goto cleanup;
3530 }
3531
David Sedlák8985a142019-07-31 16:43:06 +02003532 mod_p->parsing = 0;
3533 *submod = mod_p;
3534
3535cleanup:
3536 if (ret) {
3537 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003538 yin_parser_ctx_free(*yin_ctx);
3539 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003540 }
David Sedlák8985a142019-07-31 16:43:06 +02003541 return ret;
3542}
3543
3544LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003545yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003546{
David Sedláke4889912018-11-02 09:52:40 +01003547 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003548 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003549 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003550
David Sedlák8985a142019-07-31 16:43:06 +02003551 /* create context */
3552 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003553 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003554 (*yin_ctx)->format = LYS_IN_YIN;
3555 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, data, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003556
David Sedlák8985a142019-07-31 16:43:06 +02003557 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003558 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
3559 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003560 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003561 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 +01003562 ret = LY_EINVAL;
3563 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003564 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003565 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003566 ret = LY_EVALID;
3567 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003568 }
3569
David Sedlák3017da42019-02-15 09:48:04 +01003570 /* allocate module */
3571 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003572 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003573 mod_p->mod = mod;
3574 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003575
David Sedlák00250342019-06-21 14:19:39 +02003576 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003577 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003578 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003579
David Sedlákbf8a2b72019-08-14 16:48:10 +02003580 /* skip possible trailing whitespaces at end of the input */
Michal Vaskob36053d2020-03-26 15:49:30 +01003581 data = (*yin_ctx)->xmlctx->input;
3582 while (*data && isspace(*data)) {
David Sedlákbf8a2b72019-08-14 16:48:10 +02003583 data++;
David Sedlák6d781b62019-08-02 15:22:52 +02003584 }
David Sedlákbf8a2b72019-08-14 16:48:10 +02003585 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02003586 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 +02003587 ret = LY_EVALID;
3588 goto cleanup;
3589 }
3590
David Sedlák3017da42019-02-15 09:48:04 +01003591 mod_p->parsing = 0;
3592 mod->parsed = mod_p;
3593
3594cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003595 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003596 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003597 yin_parser_ctx_free(*yin_ctx);
3598 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003599 }
David Sedlák2e411422018-12-17 02:35:39 +01003600 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003601}