blob: 4dfda0b5a33d2d6dde03c8e3b5d339918b1684c2 [file] [log] [blame]
Radek Krejci335332a2019-09-05 13:03:35 +02001/**
2 * @file parser_stmt.c
3 * @author Radek Krejčí <rkrejci@cesnet.cz>
4 * @brief Parser of the extension substatements.
5 *
6 * Copyright (c) 2019 CESNET, z.s.p.o.
7 *
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
13 */
14
Radek Krejci335332a2019-09-05 13:03:35 +020015#include <assert.h>
16#include <ctype.h>
17#include <errno.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020018#include <stdint.h>
19#include <stdlib.h>
20#include <string.h>
Radek Krejci335332a2019-09-05 13:03:35 +020021
Radek Krejci535ea9f2020-05-29 16:01:05 +020022#include "common.h"
23#include "dict.h"
Radek Krejci47fab892020-11-05 17:02:41 +010024#include "log.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020025#include "parser_schema.h"
Michal Vasko69730152020-10-09 16:30:07 +020026#include "path.h"
Michal Vasko1a7a7bd2020-10-16 14:39:15 +020027#include "schema_compile.h"
Radek Krejci77114102021-03-10 15:21:57 +010028#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020029#include "tree.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010030#include "tree_edit.h"
Radek Krejci335332a2019-09-05 13:03:35 +020031#include "tree_schema.h"
32#include "tree_schema_internal.h"
33
Radek Krejci76c8c4e2021-02-17 10:16:48 +010034static LY_ERR lysp_stmt_container(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
35 struct lysp_node **siblings);
36static LY_ERR lysp_stmt_choice(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
37 struct lysp_node **siblings);
38static LY_ERR lysp_stmt_case(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
39 struct lysp_node **siblings);
40static LY_ERR lysp_stmt_uses(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
41 struct lysp_node **siblings);
42static LY_ERR lysp_stmt_grouping(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
43 struct lysp_node_grp **groupings);
44static LY_ERR lysp_stmt_list(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
45 struct lysp_node **siblings);
46
Radek Krejci335332a2019-09-05 13:03:35 +020047static LY_ERR
48lysp_stmt_validate_value(struct lys_parser_ctx *ctx, enum yang_arg val_type, const char *val)
49{
Radek Krejci857189e2020-09-01 13:26:36 +020050 uint8_t prefix = 0;
51 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +020052 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +020053 size_t utf8_char_len;
54
55 while (*val) {
56 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +020057 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +020058
59 switch (val_type) {
60 case Y_IDENTIF_ARG:
61 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
62 break;
63 case Y_PREF_IDENTIF_ARG:
64 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
65 break;
66 case Y_STR_ARG:
67 case Y_MAYBE_STR_ARG:
68 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
69 break;
70 }
71 first = 0;
72 }
73
74 return LY_SUCCESS;
75}
76
77/**
78 * @brief Parse extension instance.
79 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +010080 * @param[in] ctx parser context.
81 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +010082 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +020083 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
84 * @param[in,out] exts Extension instances to add to.
85 *
86 * @return LY_ERR values.
87 */
88static LY_ERR
Radek Krejcifc596f92021-02-26 22:40:26 +010089lysp_stmt_ext(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +020090 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +020091{
92 struct lysp_ext_instance *e;
93
Michal Vaskob36053d2020-03-26 15:49:30 +010094 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +020095
96 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +020097 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +010098 e->parent_stmt = insubstmt;
99 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200100 e->parsed = NULL;
Radek Krejci335332a2019-09-05 13:03:35 +0200101 /* TODO (duplicate) e->child = stmt->child; */
102
103 /* get optional argument */
104 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200105 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200106 }
107
108 return LY_SUCCESS;
109}
110
111/**
112 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
113 * description, etc...
114 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100115 * @param[in] ctx parser context.
116 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200117 * @param[in] substmt_index Index of this substatement.
118 * @param[in,out] value Place to store the parsed value.
119 * @param[in] arg Type of the YANG keyword argument (of the value).
120 * @param[in,out] exts Extension instances to add to.
121 *
122 * @return LY_ERR values.
123 */
124static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100125lysp_stmt_text_field(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index,
Radek Krejci0f969882020-08-21 16:56:47 +0200126 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200127{
Radek Krejci335332a2019-09-05 13:03:35 +0200128 if (*value) {
Radek Krejci3972b332021-03-02 16:34:31 +0100129 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200130 return LY_EVALID;
131 }
132
133 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200134 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200135
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100136 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
137 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200138 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100139 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200140 break;
141 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100142 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200143 return LY_EVALID;
144 }
145 }
146 return LY_SUCCESS;
147}
148
149/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200150 * @brief Parse a qname that can have more instances such as if-feature.
151 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100152 * @param[in] ctx parser context.
153 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200154 * @param[in,out] qnames Parsed qnames to add to.
155 * @param[in] arg Type of the expected argument.
156 * @param[in,out] exts Extension instances to add to.
157 *
158 * @return LY_ERR values.
159 */
160static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100161lysp_stmt_qnames(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
Michal Vasko7f45cf22020-10-01 12:49:44 +0200162 struct lysp_qname **qnames, enum yang_arg arg, struct lysp_ext_instance **exts)
163{
164 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200165
166 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
167
168 /* allocate new pointer */
169 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
170 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100171 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200172
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100173 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
174 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200175 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100176 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200177 break;
178 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100179 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200180 return LY_EVALID;
181 }
182 }
183 return LY_SUCCESS;
184}
185
186/**
Radek Krejci335332a2019-09-05 13:03:35 +0200187 * @brief Parse a generic text field that can have more instances such as base.
188 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100189 * @param[in] ctx parser context.
190 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200191 * @param[in,out] texts Parsed values to add to.
192 * @param[in] arg Type of the expected argument.
193 * @param[in,out] exts Extension instances to add to.
194 *
195 * @return LY_ERR values.
196 */
197static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100198lysp_stmt_text_fields(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200199 const char ***texts, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200200{
201 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200202
203 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
204
205 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100206 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200207 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200208
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100209 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
210 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200211 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100212 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200213 break;
214 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100215 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200216 return LY_EVALID;
217 }
218 }
219 return LY_SUCCESS;
220}
221
222/**
223 * @brief Parse the status statement.
224 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100225 * @param[in] ctx parser context.
226 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200227 * @param[in,out] flags Flags to add to.
228 * @param[in,out] exts Extension instances to add to.
229 *
230 * @return LY_ERR values.
231 */
232static LY_ERR
233lysp_stmt_status(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
234{
235 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200236
237 if (*flags & LYS_STATUS_MASK) {
238 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
239 return LY_EVALID;
240 }
241
242 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
243 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100244 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200245 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100246 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200247 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100248 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200249 *flags |= LYS_STATUS_OBSLT;
250 } else {
251 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
252 return LY_EVALID;
253 }
254
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100255 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
256 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200257 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100258 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200259 break;
260 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100261 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200262 return LY_EVALID;
263 }
264 }
265 return LY_SUCCESS;
266}
267
268/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100269 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200270 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100271 * @param[in] ctx parser context.
272 * @param[in] stmt Source statement data from the parsed extension instance.
273 * @param[in,out] when_p When pointer to parse to.
274 *
275 * @return LY_ERR values.
276 */
277static LY_ERR
278lysp_stmt_when(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
279{
280 LY_ERR ret = LY_SUCCESS;
281 struct lysp_when *when;
282
283 if (*when_p) {
284 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
285 return LY_EVALID;
286 }
287
288 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
289
290 when = calloc(1, sizeof *when);
291 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
292 *when_p = when;
293
294 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
295
296 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
297 switch (child->kw) {
298 case LY_STMT_DESCRIPTION:
299 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
300 break;
301 case LY_STMT_REFERENCE:
302 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
303 break;
304 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100305 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100306 break;
307 default:
308 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "when");
309 return LY_EVALID;
310 }
311 }
312 return ret;
313}
314
315/**
316 * @brief Parse the config statement.
317 *
318 * @param[in] ctx parser context.
319 * @param[in] stmt Source statement data from the parsed extension instance.
320 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200321 * @param[in,out] exts Extension instances to add to.
322 *
323 * @return LY_ERR values.
324 */
325static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100326lysp_stmt_config(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200327{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100328 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200329
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100330 if (*flags & LYS_CONFIG_MASK) {
331 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
332 return LY_EVALID;
333 }
334
335 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
336 arg_len = strlen(stmt->arg);
337 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
338 *flags |= LYS_CONFIG_W;
339 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
340 *flags |= LYS_CONFIG_R;
341 } else {
342 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
343 return LY_EVALID;
344 }
345
346 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
347 switch (child->kw) {
348 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100349 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100350 break;
351 default:
352 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "config");
353 return LY_EVALID;
354 }
355 }
356
357 return LY_SUCCESS;
358}
359
360/**
361 * @brief Parse the mandatory statement.
362 *
363 * @param[in] ctx parser context.
364 * @param[in] stmt Source statement data from the parsed extension instance.
365 * @param[in,out] flags Flags to add to.
366 * @param[in,out] exts Extension instances to add to.
367 *
368 * @return LY_ERR values.
369 */
370static LY_ERR
371lysp_stmt_mandatory(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
372{
373 size_t arg_len;
374
375 if (*flags & LYS_MAND_MASK) {
376 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
377 return LY_EVALID;
378 }
379
380 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
381 arg_len = strlen(stmt->arg);
382 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
383 *flags |= LYS_MAND_TRUE;
384 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
385 *flags |= LYS_MAND_FALSE;
386 } else {
387 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
388 return LY_EVALID;
389 }
390
391 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
392 switch (child->kw) {
393 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100394 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100395 break;
396 default:
397 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "mandatory");
398 return LY_EVALID;
399 }
400 }
401
402 return LY_SUCCESS;
403}
404
405/**
406 * @brief Parse a restriction such as range or length.
407 *
408 * @param[in] ctx parser context.
409 * @param[in] stmt Source statement data from the parsed extension instance.
410 * @param[in,out] exts Extension instances to add to.
411 *
412 * @return LY_ERR values.
413 */
414static LY_ERR
415lysp_stmt_restr(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
416{
Radek Krejci335332a2019-09-05 13:03:35 +0200417 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200418 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100419 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200420
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100421 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
422 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200423 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100424 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200425 break;
426 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100427 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200428 break;
429 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100430 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200431 break;
432 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100433 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200434 break;
435 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100436 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200437 break;
438 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100439 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200440 return LY_EVALID;
441 }
442 }
443 return LY_SUCCESS;
444}
445
446/**
447 * @brief Parse a restriction that can have more instances such as must.
448 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100449 * @param[in] ctx parser context.
450 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200451 * @param[in,out] restrs Restrictions to add to.
452 *
453 * @return LY_ERR values.
454 */
455static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100456lysp_stmt_restrs(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200457{
458 struct lysp_restr *restr;
459
Michal Vaskob36053d2020-03-26 15:49:30 +0100460 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100461 return lysp_stmt_restr(ctx, stmt, restr);
462}
463
464/**
465 * @brief Parse the anydata or anyxml statement.
466 *
467 * @param[in] ctx parser context.
468 * @param[in] stmt Source statement data from the parsed extension instance.
469 * @param[in,out] siblings Siblings to add to.
470 *
471 * @return LY_ERR values.
472 */
473static LY_ERR
474lysp_stmt_any(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
475{
476 struct lysp_node_anydata *any;
477
478 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
479
480 /* create new structure and insert into siblings */
481 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
482
483 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
484 any->parent = parent;
485
486 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
487
488 /* parse substatements */
489 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
490 switch (child->kw) {
491 case LY_STMT_CONFIG:
492 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
493 break;
494 case LY_STMT_DESCRIPTION:
495 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
496 break;
497 case LY_STMT_IF_FEATURE:
498 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
499 break;
500 case LY_STMT_MANDATORY:
501 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
502 break;
503 case LY_STMT_MUST:
504 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
505 break;
506 case LY_STMT_REFERENCE:
507 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
508 break;
509 case LY_STMT_STATUS:
510 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
511 break;
512 case LY_STMT_WHEN:
513 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
514 break;
515 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100516 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100517 break;
518 default:
519 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
520 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(LY_STMT_ANYDATA) : ly_stmt2str(LY_STMT_ANYXML));
521 return LY_EVALID;
522 }
523 }
524
525 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200526}
527
528/**
529 * @brief Parse the value or position statement. Substatement of type enum statement.
530 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100531 * @param[in] ctx parser context.
532 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200533 * @param[in,out] value Value to write to.
534 * @param[in,out] flags Flags to write to.
535 * @param[in,out] exts Extension instances to add to.
536 *
537 * @return LY_ERR values.
538 */
539static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100540lysp_stmt_type_enum_value_pos(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, int64_t *value, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +0200541 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200542{
543 size_t arg_len;
544 char *ptr = NULL;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200545 long long int num = 0;
546 unsigned long long int unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200547
548 if (*flags & LYS_SET_VALUE) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100549 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200550 return LY_EVALID;
551 }
552 *flags |= LYS_SET_VALUE;
553
554 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
555
556 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100557 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
558 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
559 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200560 goto error;
561 }
562
563 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100564 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200565 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200566 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100567 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200568 goto error;
569 }
570 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200571 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200572 if (unum > UINT64_C(4294967295)) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100573 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200574 goto error;
575 }
576 }
577 /* we have not parsed the whole argument */
578 if ((size_t)(ptr - stmt->arg) != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100579 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200580 goto error;
581 }
582 if (errno == ERANGE) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100583 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200584 goto error;
585 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100586 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200587 *value = num;
588 } else {
589 *value = unum;
590 }
591
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100592 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
593 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200594 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100595 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw == LY_STMT_VALUE ? LY_STMT_VALUE : LY_STMT_POSITION, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200596 break;
597 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100598 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200599 return LY_EVALID;
600 }
601 }
602 return LY_SUCCESS;
603
604error:
605 return LY_EVALID;
606}
607
608/**
609 * @brief Parse the enum or bit statement. Substatement of type statement.
610 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100611 * @param[in] ctx parser context.
612 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200613 * @param[in,out] enums Enums or bits to add to.
614 *
615 * @return LY_ERR values.
616 */
617static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100618lysp_stmt_type_enum(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +0200619{
620 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200621
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100622 LY_CHECK_RET(lysp_stmt_validate_value(ctx, stmt->kw == LY_STMT_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, stmt->arg));
Radek Krejci335332a2019-09-05 13:03:35 +0200623
Michal Vaskob36053d2020-03-26 15:49:30 +0100624 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200625
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100626 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +0200627 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
628 } /* else nothing specific for YANG_BIT */
629
Radek Krejci011e4aa2020-09-04 15:22:31 +0200630 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100631 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +0200632
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100633 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
634 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200635 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100636 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200637 break;
638 case LY_STMT_IF_FEATURE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100639 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(stmt->kw));
640 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200641 break;
642 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100643 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200644 break;
645 case LY_STMT_STATUS:
646 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
647 break;
648 case LY_STMT_VALUE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100649 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
650 ly_stmt2str(stmt->kw)), LY_EVALID);
651 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200652 break;
653 case LY_STMT_POSITION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100654 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
655 ly_stmt2str(stmt->kw)), LY_EVALID);
656 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200657 break;
658 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100659 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200660 break;
661 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100662 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200663 return LY_EVALID;
664 }
665 }
666 return LY_SUCCESS;
667}
668
669/**
670 * @brief Parse the fraction-digits statement. Substatement of type statement.
671 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100672 * @param[in] ctx parser context.
673 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200674 * @param[in,out] fracdig Value to write to.
675 * @param[in,out] exts Extension instances to add to.
676 *
677 * @return LY_ERR values.
678 */
679static LY_ERR
680lysp_stmt_type_fracdigits(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig, struct lysp_ext_instance **exts)
681{
682 char *ptr;
683 size_t arg_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200684 unsigned long long int num;
Radek Krejci335332a2019-09-05 13:03:35 +0200685
686 if (*fracdig) {
687 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
688 return LY_EVALID;
689 }
690
691 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
692 arg_len = strlen(stmt->arg);
693 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
694 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
695 return LY_EVALID;
696 }
697
698 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200699 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200700 /* we have not parsed the whole argument */
701 if ((size_t)(ptr - stmt->arg) != arg_len) {
702 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
703 return LY_EVALID;
704 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100705 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200706 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
707 return LY_EVALID;
708 }
709 *fracdig = num;
710
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100711 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
712 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200713 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100714 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200715 break;
716 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100717 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +0200718 return LY_EVALID;
719 }
720 }
721 return LY_SUCCESS;
722}
723
724/**
725 * @brief Parse the require-instance statement. Substatement of type statement.
726 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100727 * @param[in] ctx parser context.
728 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200729 * @param[in,out] reqinst Value to write to.
730 * @param[in,out] flags Flags to write to.
731 * @param[in,out] exts Extension instances to add to.
732 *
733 * @return LY_ERR values.
734 */
735static LY_ERR
736lysp_stmt_type_reqinstance(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *reqinst, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +0200737 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200738{
739 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200740
741 if (*flags & LYS_SET_REQINST) {
742 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
743 return LY_EVALID;
744 }
745 *flags |= LYS_SET_REQINST;
746
747 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
748 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100749 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200750 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100751 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200752 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
753 return LY_EVALID;
754 }
755
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100756 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
757 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200758 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100759 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200760 break;
761 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100762 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +0200763 return LY_EVALID;
764 }
765 }
766 return LY_SUCCESS;
767}
768
769/**
770 * @brief Parse the modifier statement. Substatement of type pattern statement.
771 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100772 * @param[in] ctx parser context.
773 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200774 * @param[in,out] pat Value to write to.
775 * @param[in,out] exts Extension instances to add to.
776 *
777 * @return LY_ERR values.
778 */
779static LY_ERR
780lysp_stmt_type_pattern_modifier(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, const char **pat, struct lysp_ext_instance **exts)
781{
782 size_t arg_len;
783 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +0200784
Radek Krejcif13b87b2020-12-01 22:02:17 +0100785 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +0200786 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
787 return LY_EVALID;
788 }
789
790 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
791 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100792 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200793 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
794 return LY_EVALID;
795 }
796
797 /* replace the value in the dictionary */
798 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100799 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200800 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100801 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +0200802
Radek Krejcif13b87b2020-12-01 22:02:17 +0100803 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
804 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200805 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +0200806
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100807 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
808 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200809 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100810 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200811 break;
812 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100813 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +0200814 return LY_EVALID;
815 }
816 }
817 return LY_SUCCESS;
818}
819
820/**
821 * @brief Parse the pattern statement. Substatement of type statement.
822 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100823 * @param[in] ctx parser context.
824 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200825 * @param[in,out] patterns Restrictions to add to.
826 *
827 * @return LY_ERR values.
828 */
829static LY_ERR
830lysp_stmt_type_pattern(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
831{
832 char *buf;
833 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200834 struct lysp_restr *restr;
835
836 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +0100837 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200838 arg_len = strlen(stmt->arg);
839
840 /* add special meaning first byte */
841 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100842 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200843 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100844 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +0200845 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +0200846 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100847 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200848
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100849 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
850 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200851 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100852 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200853 break;
854 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100855 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200856 break;
857 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100858 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200859 break;
860 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100861 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200862 break;
863 case LY_STMT_MODIFIER:
864 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +0200865 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200866 break;
867 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100868 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200869 break;
870 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100871 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +0200872 return LY_EVALID;
873 }
874 }
875 return LY_SUCCESS;
876}
877
878/**
879 * @brief Parse the type statement.
880 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100881 * @param[in] ctx parser context.
882 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200883 * @param[in,out] type Type to wrote to.
884 *
885 * @return LY_ERR values.
886 */
887static LY_ERR
888lysp_stmt_type(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
889{
890 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +0200891 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +0200892 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +0200893
894 if (type->name) {
895 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
896 return LY_EVALID;
897 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100898
899 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200900 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100901 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200902
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100903 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
904 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200905 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100906 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200907 type->flags |= LYS_SET_BASE;
908 break;
909 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100910 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +0200911 type->flags |= LYS_SET_BIT;
912 break;
913 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100914 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +0200915 type->flags |= LYS_SET_ENUM;
916 break;
917 case LY_STMT_FRACTION_DIGITS:
918 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
919 type->flags |= LYS_SET_FRDIGITS;
920 break;
921 case LY_STMT_LENGTH:
922 if (type->length) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100923 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200924 return LY_EVALID;
925 }
926 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100927 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200928
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100929 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +0200930 type->flags |= LYS_SET_LENGTH;
931 break;
932 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100933 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +0200934 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +0200935 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200936 lydict_remove(PARSER_CTX(ctx), str_path);
937 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +0200938 type->flags |= LYS_SET_PATH;
939 break;
940 case LY_STMT_PATTERN:
941 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
942 type->flags |= LYS_SET_PATTERN;
943 break;
944 case LY_STMT_RANGE:
945 if (type->range) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100946 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200947 return LY_EVALID;
948 }
949 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100950 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200951
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100952 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +0200953 type->flags |= LYS_SET_RANGE;
954 break;
955 case LY_STMT_REQUIRE_INSTANCE:
956 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100957 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +0200958 break;
959 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +0100960 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200961 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
962 type->flags |= LYS_SET_TYPE;
963 break;
964 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100965 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200966 break;
967 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100968 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +0200969 return LY_EVALID;
970 }
971 }
972 return LY_SUCCESS;
973}
974
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100975/**
976 * @brief Parse the leaf statement.
977 *
978 * @param[in] ctx parser context.
979 * @param[in] stmt Source statement data from the parsed extension instance.
980 * @param[in] parent Parent node to connect to (not into).
981 * @param[in,out] siblings Siblings to add to.
982 *
983 * @return LY_ERR values.
984 */
985static LY_ERR
986lysp_stmt_leaf(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
987{
988 struct lysp_node_leaf *leaf;
989
990 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
991
992 /* create new leaf structure */
993 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
994 leaf->nodetype = LYS_LEAF;
995 leaf->parent = parent;
996
997 /* get name */
998 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
999
1000 /* parse substatements */
1001 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1002 switch (child->kw) {
1003 case LY_STMT_CONFIG:
1004 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1005 break;
1006 case LY_STMT_DEFAULT:
1007 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dflt.str, Y_STR_ARG, &leaf->exts));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001008 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001009 break;
1010 case LY_STMT_DESCRIPTION:
1011 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1012 break;
1013 case LY_STMT_IF_FEATURE:
1014 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1015 break;
1016 case LY_STMT_MANDATORY:
1017 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1018 break;
1019 case LY_STMT_MUST:
1020 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1021 break;
1022 case LY_STMT_REFERENCE:
1023 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1024 break;
1025 case LY_STMT_STATUS:
1026 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1027 break;
1028 case LY_STMT_TYPE:
1029 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1030 break;
1031 case LY_STMT_UNITS:
1032 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1033 break;
1034 case LY_STMT_WHEN:
1035 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1036 break;
1037 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001038 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001039 break;
1040 default:
1041 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "leaf");
1042 return LY_EVALID;
1043 }
1044 }
1045
1046 /* mandatory substatements */
1047 if (!leaf->type.name) {
1048 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1049 return LY_EVALID;
1050 }
1051
1052 return LY_SUCCESS;
1053}
1054
1055/**
1056 * @brief Parse the max-elements statement.
1057 *
1058 * @param[in] ctx parser context.
1059 * @param[in] stmt Source statement data from the parsed extension instance.
1060 * @param[in,out] max Value to write to.
1061 * @param[in,out] flags Flags to write to.
1062 * @param[in,out] exts Extension instances to add to.
1063 *
1064 * @return LY_ERR values.
1065 */
1066static LY_ERR
1067lysp_stmt_maxelements(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
1068 uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
1069{
1070 size_t arg_len;
1071 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001072 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001073
1074 if (*flags & LYS_SET_MAX) {
1075 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1076 return LY_EVALID;
1077 }
1078 *flags |= LYS_SET_MAX;
1079
1080 /* get value */
1081 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1082 arg_len = strlen(stmt->arg);
1083
1084 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1085 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1086 return LY_EVALID;
1087 }
1088
1089 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1090 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001091 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001092 /* we have not parsed the whole argument */
1093 if ((size_t)(ptr - stmt->arg) != arg_len) {
1094 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1095 return LY_EVALID;
1096 }
1097 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1098 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1099 return LY_EVALID;
1100 }
1101
1102 *max = num;
1103 } else {
1104 /* unbounded */
1105 *max = 0;
1106 }
1107
1108 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1109 switch (child->kw) {
1110 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001111 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001112 break;
1113 default:
1114 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "max-elements");
1115 return LY_EVALID;
1116 }
1117 }
1118
1119 return LY_SUCCESS;
1120}
1121
1122/**
1123 * @brief Parse the min-elements statement.
1124 *
1125 * @param[in] ctx parser context.
1126 * @param[in] stmt Source statement data from the parsed extension instance.
1127 * @param[in,out] min Value to write to.
1128 * @param[in,out] flags Flags to write to.
1129 * @param[in,out] exts Extension instances to add to.
1130 *
1131 * @return LY_ERR values.
1132 */
1133static LY_ERR
1134lysp_stmt_minelements(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
1135 uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
1136{
1137 size_t arg_len;
1138 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001139 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001140
1141 if (*flags & LYS_SET_MIN) {
1142 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
1143 return LY_EVALID;
1144 }
1145 *flags |= LYS_SET_MIN;
1146
1147 /* get value */
1148 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1149 arg_len = strlen(stmt->arg);
1150
1151 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
1152 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1153 return LY_EVALID;
1154 }
1155
1156 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001157 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001158 /* we have not parsed the whole argument */
1159 if ((size_t)(ptr - stmt->arg) != arg_len) {
1160 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1161 return LY_EVALID;
1162 }
1163 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1164 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
1165 return LY_EVALID;
1166 }
1167 *min = num;
1168
1169 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1170 switch (child->kw) {
1171 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001172 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001173 break;
1174 default:
1175 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "min-elements");
1176 return LY_EVALID;
1177 }
1178 }
1179
1180 return LY_SUCCESS;
1181}
1182
1183/**
1184 * @brief Parse the ordered-by statement.
1185 *
1186 * @param[in] ctx parser context.
1187 * @param[in] stmt Source statement data from the parsed extension instance.
1188 * @param[in,out] flags Flags to write to.
1189 * @param[in,out] exts Extension instances to add to.
1190 *
1191 * @return LY_ERR values.
1192 */
1193static LY_ERR
1194lysp_stmt_orderedby(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1195{
1196 size_t arg_len;
1197
1198 if (*flags & LYS_ORDBY_MASK) {
1199 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
1200 return LY_EVALID;
1201 }
1202
1203 /* get value */
1204 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1205 arg_len = strlen(stmt->arg);
1206 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
1207 *flags |= LYS_MAND_TRUE;
1208 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
1209 *flags |= LYS_MAND_FALSE;
1210 } else {
1211 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
1212 return LY_EVALID;
1213 }
1214
1215 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1216 switch (child->kw) {
1217 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001218 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001219 break;
1220 default:
1221 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "ordered-by");
1222 return LY_EVALID;
1223 }
1224 }
1225
1226 return LY_SUCCESS;
1227}
1228
1229/**
1230 * @brief Parse the leaf-list statement.
1231 *
1232 * @param[in] ctx parser context.
1233 * @param[in] stmt Source statement data from the parsed extension instance.
1234 * @param[in] parent Parent node to connect to (not into).
1235 * @param[in,out] siblings Siblings to add to.
1236 *
1237 * @return LY_ERR values.
1238 */
1239static LY_ERR
1240lysp_stmt_leaflist(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
1241{
1242 struct lysp_node_leaflist *llist;
1243
1244 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1245
1246 /* create new leaf-list structure */
1247 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
1248 llist->nodetype = LYS_LEAFLIST;
1249 llist->parent = parent;
1250
1251 /* get name */
1252 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
1253
1254 /* parse substatements */
1255 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1256 switch (child->kw) {
1257 case LY_STMT_CONFIG:
1258 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
1259 break;
1260 case LY_STMT_DEFAULT:
1261 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
1262 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
1263 break;
1264 case LY_STMT_DESCRIPTION:
1265 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
1266 break;
1267 case LY_STMT_IF_FEATURE:
1268 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
1269 break;
1270 case LY_STMT_MAX_ELEMENTS:
1271 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
1272 break;
1273 case LY_STMT_MIN_ELEMENTS:
1274 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
1275 break;
1276 case LY_STMT_MUST:
1277 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
1278 break;
1279 case LY_STMT_ORDERED_BY:
1280 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
1281 break;
1282 case LY_STMT_REFERENCE:
1283 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
1284 break;
1285 case LY_STMT_STATUS:
1286 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
1287 break;
1288 case LY_STMT_TYPE:
1289 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
1290 break;
1291 case LY_STMT_UNITS:
1292 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
1293 break;
1294 case LY_STMT_WHEN:
1295 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
1296 break;
1297 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001298 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001299 break;
1300 default:
1301 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "llist");
1302 return LY_EVALID;
1303 }
1304 }
1305
1306 /* mandatory substatements */
1307 if (!llist->type.name) {
1308 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
1309 return LY_EVALID;
1310 }
1311
1312 return LY_SUCCESS;
1313}
1314
1315/**
1316 * @brief Parse the refine statement.
1317 *
1318 * @param[in] ctx parser context.
1319 * @param[in] stmt Source statement data from the parsed extension instance.
1320 * @param[in,out] refines Refines to add to.
1321 *
1322 * @return LY_ERR values.
1323 */
1324static LY_ERR
1325lysp_stmt_refine(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
1326{
1327 struct lysp_refine *rf;
1328
1329 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1330
1331 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
1332
1333 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
1334
1335 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1336 switch (child->kw) {
1337 case LY_STMT_CONFIG:
1338 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
1339 break;
1340 case LY_STMT_DEFAULT:
1341 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
1342 break;
1343 case LY_STMT_DESCRIPTION:
1344 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
1345 break;
1346 case LY_STMT_IF_FEATURE:
1347 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
1348 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
1349 break;
1350 case LY_STMT_MAX_ELEMENTS:
1351 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
1352 break;
1353 case LY_STMT_MIN_ELEMENTS:
1354 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
1355 break;
1356 case LY_STMT_MUST:
1357 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
1358 break;
1359 case LY_STMT_MANDATORY:
1360 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
1361 break;
1362 case LY_STMT_REFERENCE:
1363 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
1364 break;
1365 case LY_STMT_PRESENCE:
1366 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
1367 break;
1368 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001369 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001370 break;
1371 default:
1372 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "refine");
1373 return LY_EVALID;
1374 }
1375 }
1376
1377 return LY_SUCCESS;
1378}
1379
1380/**
1381 * @brief Parse the typedef statement.
1382 *
1383 * @param[in] ctx parser context.
1384 * @param[in] stmt Source statement data from the parsed extension instance.
1385 * @param[in] parent Parent node to connect to (not into).
1386 * @param[in,out] typedefs Typedefs to add to.
1387 *
1388 * @return LY_ERR values.
1389 */
1390static LY_ERR
1391lysp_stmt_typedef(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_tpdf **typedefs)
1392{
1393 struct lysp_tpdf *tpdf;
1394
1395 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1396
1397 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
1398
1399 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
1400
1401 /* parse substatements */
1402 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1403 switch (child->kw) {
1404 case LY_STMT_DEFAULT:
1405 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dflt.str, Y_STR_ARG, &tpdf->exts));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001406 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001407 break;
1408 case LY_STMT_DESCRIPTION:
1409 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
1410 break;
1411 case LY_STMT_REFERENCE:
1412 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
1413 break;
1414 case LY_STMT_STATUS:
1415 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
1416 break;
1417 case LY_STMT_TYPE:
1418 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
1419 break;
1420 case LY_STMT_UNITS:
1421 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
1422 break;
1423 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001424 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001425 break;
1426 default:
1427 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "typedef");
1428 return LY_EVALID;
1429 }
1430 }
1431
1432 /* mandatory substatements */
1433 if (!tpdf->type.name) {
1434 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
1435 return LY_EVALID;
1436 }
1437
1438 /* store data for collision check */
1439 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
1440 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
1441 }
1442
1443 return LY_SUCCESS;
1444}
1445
1446/**
1447 * @brief Parse the input or output statement.
1448 *
1449 * @param[in] ctx parser context.
1450 * @param[in] stmt Source statement data from the parsed extension instance.
1451 * @param[in] parent Parent node to connect to (not into).
1452 * @param[in,out] inout_p Input/output pointer to write to.
1453 *
1454 * @return LY_ERR values.
1455 */
1456static LY_ERR
1457lysp_stmt_inout(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
1458 struct lysp_node_action_inout *inout_p)
1459{
1460 if (inout_p->nodetype) {
1461 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
1462 return LY_EVALID;
1463 }
1464
1465 /* initiate structure */
1466 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
1467 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
1468 inout_p->parent = parent;
1469
1470 /* parse substatements */
1471 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1472 switch (child->kw) {
1473 case LY_STMT_ANYDATA:
1474 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(stmt->kw));
1475 /* fall through */
1476 case LY_STMT_ANYXML:
1477 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
1478 break;
1479 case LY_STMT_CHOICE:
1480 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
1481 break;
1482 case LY_STMT_CONTAINER:
1483 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
1484 break;
1485 case LY_STMT_LEAF:
1486 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
1487 break;
1488 case LY_STMT_LEAF_LIST:
1489 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
1490 break;
1491 case LY_STMT_LIST:
1492 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
1493 break;
1494 case LY_STMT_USES:
1495 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
1496 break;
1497 case LY_STMT_TYPEDEF:
1498 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
1499 break;
1500 case LY_STMT_MUST:
1501 PARSER_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(stmt->kw));
1502 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
1503 break;
1504 case LY_STMT_GROUPING:
1505 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
1506 break;
1507 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001508 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001509 break;
1510 default:
1511 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
1512 return LY_EVALID;
1513 }
1514 }
1515
1516 if (!inout_p->child) {
1517 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(stmt->kw));
1518 return LY_EVALID;
1519 }
1520
1521 return LY_SUCCESS;
1522}
1523
1524/**
1525 * @brief Parse the action statement.
1526 *
1527 * @param[in] ctx parser context.
1528 * @param[in] stmt Source statement data from the parsed extension instance.
1529 * @param[in] parent Parent node to connect to (not into).
1530 * @param[in,out] actions Actions to add to.
1531 *
1532 * @return LY_ERR values.
1533 */
1534static LY_ERR
1535lysp_stmt_action(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node_action **actions)
1536{
1537 struct lysp_node_action *act;
1538
1539 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1540
1541 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
1542
1543 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
1544 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
1545 act->parent = parent;
1546
1547 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1548 switch (child->kw) {
1549 case LY_STMT_DESCRIPTION:
1550 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
1551 break;
1552 case LY_STMT_IF_FEATURE:
1553 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
1554 break;
1555 case LY_STMT_REFERENCE:
1556 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
1557 break;
1558 case LY_STMT_STATUS:
1559 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
1560 break;
1561
1562 case LY_STMT_INPUT:
1563 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
1564 break;
1565 case LY_STMT_OUTPUT:
1566 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
1567 break;
1568
1569 case LY_STMT_TYPEDEF:
1570 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
1571 break;
1572 case LY_STMT_GROUPING:
1573 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
1574 break;
1575 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001576 LY_CHECK_RET(lysp_stmt_ext(ctx, child, parent ? LY_STMT_ACTION : LY_STMT_RPC, 0, &act->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001577 break;
1578 default:
1579 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), parent ? "action" : "rpc");
1580 return LY_EVALID;
1581 }
1582 }
1583
1584 /* always initialize inout, they are technically present (needed for later deviations/refines) */
1585 if (!act->input.nodetype) {
1586 act->input.nodetype = LYS_INPUT;
1587 act->input.parent = &act->node;
1588 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
1589 }
1590 if (!act->output.nodetype) {
1591 act->output.nodetype = LYS_OUTPUT;
1592 act->output.parent = &act->node;
1593 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
1594 }
1595
1596 return LY_SUCCESS;
1597}
1598
1599/**
1600 * @brief Parse the notification statement.
1601 *
1602 * @param[in] ctx parser context.
1603 * @param[in] stmt Source statement data from the parsed extension instance.
1604 * @param[in] parent Parent node to connect to (not into).
1605 * @param[in,out] notifs Notifications to add to.
1606 *
1607 * @return LY_ERR values.
1608 */
1609static LY_ERR
1610lysp_stmt_notif(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node_notif **notifs)
1611{
1612 struct lysp_node_notif *notif;
1613
1614 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1615
1616 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
1617
1618 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
1619 notif->nodetype = LYS_NOTIF;
1620 notif->parent = parent;
1621
1622 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1623 switch (child->kw) {
1624 case LY_STMT_DESCRIPTION:
1625 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
1626 break;
1627 case LY_STMT_IF_FEATURE:
1628 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
1629 break;
1630 case LY_STMT_REFERENCE:
1631 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
1632 break;
1633 case LY_STMT_STATUS:
1634 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
1635 break;
1636
1637 case LY_STMT_ANYDATA:
1638 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
1639 /* fall through */
1640 case LY_STMT_ANYXML:
1641 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
1642 break;
1643 case LY_STMT_CHOICE:
1644 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
1645 break;
1646 case LY_STMT_CONTAINER:
1647 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
1648 break;
1649 case LY_STMT_LEAF:
1650 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
1651 break;
1652 case LY_STMT_LEAF_LIST:
1653 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
1654 break;
1655 case LY_STMT_LIST:
1656 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
1657 break;
1658 case LY_STMT_USES:
1659 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
1660 break;
1661
1662 case LY_STMT_MUST:
1663 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
1664 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
1665 break;
1666 case LY_STMT_TYPEDEF:
1667 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
1668 break;
1669 case LY_STMT_GROUPING:
1670 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
1671 break;
1672 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001673 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001674 break;
1675 default:
1676 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "notification");
1677 return LY_EVALID;
1678 }
1679 }
1680
1681 return LY_SUCCESS;
1682}
1683
1684/**
1685 * @brief Parse the grouping statement.
1686 *
1687 * @param[in] ctx parser context.
1688 * @param[in] stmt Source statement data from the parsed extension instance.
1689 * @param[in] parent Parent node to connect to (not into).
1690 * @param[in,out] groupings Groupings to add to.
1691 *
1692 * @return LY_ERR values.
1693 */
1694static LY_ERR
1695lysp_stmt_grouping(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node_grp **groupings)
1696{
1697 struct lysp_node_grp *grp;
1698
1699 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1700
1701 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
1702
1703 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
1704 grp->nodetype = LYS_GROUPING;
1705 grp->parent = parent;
1706
1707 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1708 switch (child->kw) {
1709 case LY_STMT_DESCRIPTION:
1710 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
1711 break;
1712 case LY_STMT_REFERENCE:
1713 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
1714 break;
1715 case LY_STMT_STATUS:
1716 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
1717 break;
1718
1719 case LY_STMT_ANYDATA:
1720 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
1721 /* fall through */
1722 case LY_STMT_ANYXML:
1723 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
1724 break;
1725 case LY_STMT_CHOICE:
1726 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
1727 break;
1728 case LY_STMT_CONTAINER:
1729 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
1730 break;
1731 case LY_STMT_LEAF:
1732 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
1733 break;
1734 case LY_STMT_LEAF_LIST:
1735 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
1736 break;
1737 case LY_STMT_LIST:
1738 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
1739 break;
1740 case LY_STMT_USES:
1741 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
1742 break;
1743
1744 case LY_STMT_TYPEDEF:
1745 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
1746 break;
1747 case LY_STMT_ACTION:
1748 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
1749 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
1750 break;
1751 case LY_STMT_GROUPING:
1752 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
1753 break;
1754 case LY_STMT_NOTIFICATION:
1755 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
1756 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
1757 break;
1758 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001759 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001760 break;
1761 default:
1762 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "grouping");
1763 return LY_EVALID;
1764 }
1765 }
1766
1767 return LY_SUCCESS;
1768}
1769
1770/**
1771 * @brief Parse the augment statement.
1772 *
1773 * @param[in] ctx parser context.
1774 * @param[in] stmt Source statement data from the parsed extension instance.
1775 * @param[in] parent Parent node to connect to (not into).
1776 * @param[in,out] augments Augments to add to.
1777 *
1778 * @return LY_ERR values.
1779 */
1780static LY_ERR
1781lysp_stmt_augment(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node_augment **augments)
1782{
1783 struct lysp_node_augment *aug;
1784
1785 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1786
1787 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
1788
1789 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
1790 aug->nodetype = LYS_AUGMENT;
1791 aug->parent = parent;
1792
1793 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1794 switch (child->kw) {
1795 case LY_STMT_DESCRIPTION:
1796 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
1797 break;
1798 case LY_STMT_IF_FEATURE:
1799 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
1800 break;
1801 case LY_STMT_REFERENCE:
1802 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
1803 break;
1804 case LY_STMT_STATUS:
1805 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
1806 break;
1807 case LY_STMT_WHEN:
1808 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
1809 break;
1810
1811 case LY_STMT_ANYDATA:
1812 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
1813 /* fall through */
1814 case LY_STMT_ANYXML:
1815 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
1816 break;
1817 case LY_STMT_CASE:
1818 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
1819 break;
1820 case LY_STMT_CHOICE:
1821 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
1822 break;
1823 case LY_STMT_CONTAINER:
1824 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
1825 break;
1826 case LY_STMT_LEAF:
1827 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
1828 break;
1829 case LY_STMT_LEAF_LIST:
1830 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
1831 break;
1832 case LY_STMT_LIST:
1833 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
1834 break;
1835 case LY_STMT_USES:
1836 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
1837 break;
1838
1839 case LY_STMT_ACTION:
1840 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
1841 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
1842 break;
1843 case LY_STMT_NOTIFICATION:
1844 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
1845 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
1846 break;
1847 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001848 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001849 break;
1850 default:
1851 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "augment");
1852 return LY_EVALID;
1853 }
1854 }
1855
1856 return LY_SUCCESS;
1857}
1858
1859/**
1860 * @brief Parse the uses statement.
1861 *
1862 * @param[in] ctx parser context.
1863 * @param[in] stmt Source statement data from the parsed extension instance.
1864 * @param[in] parent Parent node to connect to (not into).
1865 * @param[in,out] siblings Siblings to add to.
1866 *
1867 * @return LY_ERR values.
1868 */
1869static LY_ERR
1870lysp_stmt_uses(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
1871{
1872 struct lysp_node_uses *uses;
1873
1874 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1875
1876 /* create uses structure */
1877 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
1878
1879 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
1880 uses->nodetype = LYS_USES;
1881 uses->parent = parent;
1882
1883 /* parse substatements */
1884 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1885 switch (child->kw) {
1886 case LY_STMT_DESCRIPTION:
1887 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
1888 break;
1889 case LY_STMT_IF_FEATURE:
1890 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
1891 break;
1892 case LY_STMT_REFERENCE:
1893 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
1894 break;
1895 case LY_STMT_STATUS:
1896 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
1897 break;
1898 case LY_STMT_WHEN:
1899 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
1900 break;
1901
1902 case LY_STMT_REFINE:
1903 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
1904 break;
1905 case LY_STMT_AUGMENT:
1906 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
1907 break;
1908 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001909 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001910 break;
1911 default:
1912 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "uses");
1913 return LY_EVALID;
1914 }
1915 }
1916
1917 return LY_SUCCESS;
1918}
1919
1920/**
1921 * @brief Parse the case statement.
1922 *
1923 * @param[in] ctx parser context.
1924 * @param[in] stmt Source statement data from the parsed extension instance.
1925 * @param[in] parent Parent node to connect to (not into).
1926 * @param[in,out] siblings Siblings to add to.
1927 *
1928 * @return LY_ERR values.
1929 */
1930static LY_ERR
1931lysp_stmt_case(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
1932{
1933 struct lysp_node_case *cas;
1934
1935 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1936
1937 /* create new case structure */
1938 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
1939
1940 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
1941 cas->nodetype = LYS_CASE;
1942 cas->parent = parent;
1943
1944 /* parse substatements */
1945 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1946 switch (child->kw) {
1947 case LY_STMT_DESCRIPTION:
1948 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
1949 break;
1950 case LY_STMT_IF_FEATURE:
1951 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
1952 break;
1953 case LY_STMT_REFERENCE:
1954 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
1955 break;
1956 case LY_STMT_STATUS:
1957 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
1958 break;
1959 case LY_STMT_WHEN:
1960 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
1961 break;
1962
1963 case LY_STMT_ANYDATA:
1964 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
1965 /* fall through */
1966 case LY_STMT_ANYXML:
1967 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
1968 break;
1969 case LY_STMT_CHOICE:
1970 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
1971 break;
1972 case LY_STMT_CONTAINER:
1973 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
1974 break;
1975 case LY_STMT_LEAF:
1976 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
1977 break;
1978 case LY_STMT_LEAF_LIST:
1979 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
1980 break;
1981 case LY_STMT_LIST:
1982 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
1983 break;
1984 case LY_STMT_USES:
1985 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
1986 break;
1987 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001988 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001989 break;
1990 default:
1991 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "case");
1992 return LY_EVALID;
1993 }
1994 }
1995 return LY_SUCCESS;
1996}
1997
1998/**
1999 * @brief Parse the choice statement.
2000 *
2001 * @param[in] ctx parser context.
2002 * @param[in] stmt Source statement data from the parsed extension instance.
2003 * @param[in] parent Parent node to connect to (not into).
2004 * @param[in,out] siblings Siblings to add to.
2005 *
2006 * @return LY_ERR values.
2007 */
2008static LY_ERR
2009lysp_stmt_choice(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
2010{
2011 struct lysp_node_choice *choice;
2012
2013 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2014
2015 /* create new choice structure */
2016 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2017
2018 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2019 choice->nodetype = LYS_CHOICE;
2020 choice->parent = parent;
2021
2022 /* parse substatements */
2023 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2024 switch (child->kw) {
2025 case LY_STMT_CONFIG:
2026 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2027 break;
2028 case LY_STMT_DESCRIPTION:
2029 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2030 break;
2031 case LY_STMT_IF_FEATURE:
2032 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2033 break;
2034 case LY_STMT_MANDATORY:
2035 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2036 break;
2037 case LY_STMT_REFERENCE:
2038 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2039 break;
2040 case LY_STMT_STATUS:
2041 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2042 break;
2043 case LY_STMT_WHEN:
2044 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2045 break;
2046 case LY_STMT_DEFAULT:
2047 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dflt.str, Y_PREF_IDENTIF_ARG, &choice->exts));
Michal Vasko8a67eff2021-12-07 14:04:47 +01002048 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002049 break;
2050 case LY_STMT_ANYDATA:
2051 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2052 /* fall through */
2053 case LY_STMT_ANYXML:
2054 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2055 break;
2056 case LY_STMT_CASE:
2057 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2058 break;
2059 case LY_STMT_CHOICE:
2060 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2061 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2062 break;
2063 case LY_STMT_CONTAINER:
2064 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2065 break;
2066 case LY_STMT_LEAF:
2067 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2068 break;
2069 case LY_STMT_LEAF_LIST:
2070 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2071 break;
2072 case LY_STMT_LIST:
2073 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2074 break;
2075 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002076 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002077 break;
2078 default:
2079 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "choice");
2080 return LY_EVALID;
2081 }
2082 }
2083 return LY_SUCCESS;
2084}
2085
2086/**
2087 * @brief Parse the container statement.
2088 *
2089 * @param[in] ctx parser context.
2090 * @param[in] stmt Source statement data from the parsed extension instance.
2091 * @param[in] parent Parent node to connect to (not into).
2092 * @param[in,out] siblings Siblings to add to.
2093 *
2094 * @return LY_ERR values.
2095 */
2096static LY_ERR
2097lysp_stmt_container(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
2098{
2099 struct lysp_node_container *cont;
2100
2101 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2102
2103 /* create new container structure */
2104 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2105
2106 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2107 cont->nodetype = LYS_CONTAINER;
2108 cont->parent = parent;
2109
2110 /* parse substatements */
2111 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2112 switch (child->kw) {
2113 case LY_STMT_CONFIG:
2114 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
2115 break;
2116 case LY_STMT_DESCRIPTION:
2117 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
2118 break;
2119 case LY_STMT_IF_FEATURE:
2120 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
2121 break;
2122 case LY_STMT_REFERENCE:
2123 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
2124 break;
2125 case LY_STMT_STATUS:
2126 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
2127 break;
2128 case LY_STMT_WHEN:
2129 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
2130 break;
2131 case LY_STMT_PRESENCE:
2132 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
2133 break;
2134 case LY_STMT_ANYDATA:
2135 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
2136 /* fall through */
2137 case LY_STMT_ANYXML:
2138 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
2139 break;
2140 case LY_STMT_CHOICE:
2141 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
2142 break;
2143 case LY_STMT_CONTAINER:
2144 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
2145 break;
2146 case LY_STMT_LEAF:
2147 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
2148 break;
2149 case LY_STMT_LEAF_LIST:
2150 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
2151 break;
2152 case LY_STMT_LIST:
2153 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
2154 break;
2155 case LY_STMT_USES:
2156 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
2157 break;
2158
2159 case LY_STMT_TYPEDEF:
2160 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
2161 break;
2162 case LY_STMT_MUST:
2163 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
2164 break;
2165 case LY_STMT_ACTION:
2166 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
2167 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
2168 break;
2169 case LY_STMT_GROUPING:
2170 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
2171 break;
2172 case LY_STMT_NOTIFICATION:
2173 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
2174 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
2175 break;
2176 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002177 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002178 break;
2179 default:
2180 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "container");
2181 return LY_EVALID;
2182 }
2183 }
2184
2185 return LY_SUCCESS;
2186}
2187
2188/**
2189 * @brief Parse the list statement.
2190 *
2191 * @param[in] ctx parser context.
2192 * @param[in] stmt Source statement data from the parsed extension instance.
2193 * @param[in] parent Parent node to connect to (not into).
2194 * @param[in,out] siblings Siblings to add to.
2195 *
2196 * @return LY_ERR values.
2197 */
2198static LY_ERR
2199lysp_stmt_list(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
2200{
2201 struct lysp_node_list *list;
2202
2203 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2204
2205 /* create new list structure */
2206 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
2207
2208 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
2209 list->nodetype = LYS_LIST;
2210 list->parent = parent;
2211
2212 /* parse substatements */
2213 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2214 switch (child->kw) {
2215 case LY_STMT_CONFIG:
2216 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
2217 break;
2218 case LY_STMT_DESCRIPTION:
2219 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
2220 break;
2221 case LY_STMT_IF_FEATURE:
2222 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
2223 break;
2224 case LY_STMT_REFERENCE:
2225 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
2226 break;
2227 case LY_STMT_STATUS:
2228 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
2229 break;
2230 case LY_STMT_WHEN:
2231 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
2232 break;
2233 case LY_STMT_KEY:
2234 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
2235 break;
2236 case LY_STMT_MAX_ELEMENTS:
2237 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
2238 break;
2239 case LY_STMT_MIN_ELEMENTS:
2240 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
2241 break;
2242 case LY_STMT_ORDERED_BY:
2243 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
2244 break;
2245 case LY_STMT_UNIQUE:
2246 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
2247 break;
2248
2249 case LY_STMT_ANYDATA:
2250 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
2251 /* fall through */
2252 case LY_STMT_ANYXML:
2253 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
2254 break;
2255 case LY_STMT_CHOICE:
2256 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
2257 break;
2258 case LY_STMT_CONTAINER:
2259 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
2260 break;
2261 case LY_STMT_LEAF:
2262 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
2263 break;
2264 case LY_STMT_LEAF_LIST:
2265 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
2266 break;
2267 case LY_STMT_LIST:
2268 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
2269 break;
2270 case LY_STMT_USES:
2271 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
2272 break;
2273
2274 case LY_STMT_TYPEDEF:
2275 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
2276 break;
2277 case LY_STMT_MUST:
2278 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
2279 break;
2280 case LY_STMT_ACTION:
2281 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
2282 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
2283 break;
2284 case LY_STMT_GROUPING:
2285 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
2286 break;
2287 case LY_STMT_NOTIFICATION:
2288 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
2289 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
2290 break;
2291 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002292 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002293 break;
2294 default:
2295 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "list");
2296 return LY_EVALID;
2297 }
2298 }
2299
2300 return LY_SUCCESS;
2301}
2302
Radek Krejci335332a2019-09-05 13:03:35 +02002303LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002304lysp_stmt_parse(struct lysc_ctx *ctx, const struct lysp_stmt *stmt, void **result, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02002305{
Radek Krejciad5963b2019-09-06 16:03:05 +02002306 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002307 uint16_t flags;
2308 struct lys_parser_ctx pctx = {0};
Michal Vasko8a67eff2021-12-07 14:04:47 +01002309 struct ly_set pmods = {0};
2310 void *objs;
Radek Krejci335332a2019-09-05 13:03:35 +02002311
Michal Vasko8a67eff2021-12-07 14:04:47 +01002312 /* local context */
Michal Vaskob36053d2020-03-26 15:49:30 +01002313 pctx.format = LYS_IN_YANG;
Michal Vasko8a67eff2021-12-07 14:04:47 +01002314 pctx.parsed_mods = &pmods;
2315 objs = &ctx->pmod;
2316 pmods.objs = objs;
2317 pmods.count = 1;
Radek Krejci2efc45b2020-12-22 16:25:44 +01002318
Radek Krejciddace2c2021-01-08 11:30:56 +01002319 LOG_LOCSET(NULL, NULL, ctx->path, NULL);
Radek Krejci335332a2019-09-05 13:03:35 +02002320
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002321 switch (stmt->kw) {
2322 case LY_STMT_ACTION:
2323 case LY_STMT_RPC:
2324 ret = lysp_stmt_action(&pctx, stmt, NULL, (struct lysp_node_action **)result);
2325 break;
2326 case LY_STMT_ANYDATA:
2327 case LY_STMT_ANYXML:
2328 ret = lysp_stmt_any(&pctx, stmt, NULL, (struct lysp_node **)result);
2329 break;
2330 case LY_STMT_AUGMENT:
2331 ret = lysp_stmt_augment(&pctx, stmt, NULL, (struct lysp_node_augment **)result);
2332 break;
2333 case LY_STMT_BASE:
2334 ret = lysp_stmt_text_fields(&pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
2335 break;
2336 case LY_STMT_BIT:
2337 case LY_STMT_ENUM:
2338 ret = lysp_stmt_type_enum(&pctx, stmt, (struct lysp_type_enum **)result);
2339 break;
2340 case LY_STMT_CASE:
2341 ret = lysp_stmt_case(&pctx, stmt, NULL, (struct lysp_node **)result);
2342 break;
2343 case LY_STMT_CHOICE:
2344 ret = lysp_stmt_choice(&pctx, stmt, NULL, (struct lysp_node **)result);
2345 break;
2346 case LY_STMT_CONFIG:
2347 ret = lysp_stmt_config(&pctx, stmt, *(uint16_t **)result, exts);
2348 break;
2349 case LY_STMT_CONTACT:
2350 case LY_STMT_DESCRIPTION:
2351 case LY_STMT_ERROR_APP_TAG:
2352 case LY_STMT_ERROR_MESSAGE:
2353 case LY_STMT_KEY:
2354 case LY_STMT_NAMESPACE:
2355 case LY_STMT_ORGANIZATION:
2356 case LY_STMT_PRESENCE:
2357 case LY_STMT_REFERENCE:
2358 case LY_STMT_UNITS:
2359 ret = lysp_stmt_text_field(&pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
2360 break;
2361 case LY_STMT_CONTAINER:
2362 ret = lysp_stmt_container(&pctx, stmt, NULL, (struct lysp_node **)result);
2363 break;
2364 case LY_STMT_DEFAULT:
2365 case LY_STMT_IF_FEATURE:
2366 case LY_STMT_UNIQUE:
2367 ret = lysp_stmt_qnames(&pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
2368 break;
2369 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002370 ret = lysp_stmt_ext(&pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002371 break;
2372 case LY_STMT_FRACTION_DIGITS:
2373 ret = lysp_stmt_type_fracdigits(&pctx, stmt, *(uint8_t **)result, exts);
2374 break;
2375 case LY_STMT_GROUPING:
2376 ret = lysp_stmt_grouping(&pctx, stmt, NULL, (struct lysp_node_grp **)result);
2377 break;
2378 case LY_STMT_INPUT:
2379 case LY_STMT_OUTPUT: {
2380 struct lysp_node_action_inout *inout;
2381
2382 *result = inout = calloc(1, sizeof *inout);
2383 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
2384 ret = lysp_stmt_inout(&pctx, stmt, NULL, inout);
2385 break;
2386 }
2387 case LY_STMT_LEAF:
2388 ret = lysp_stmt_leaf(&pctx, stmt, NULL, (struct lysp_node **)result);
2389 break;
2390 case LY_STMT_LEAF_LIST:
2391 ret = lysp_stmt_leaflist(&pctx, stmt, NULL, (struct lysp_node **)result);
2392 break;
2393 case LY_STMT_LENGTH:
2394 case LY_STMT_MUST:
2395 case LY_STMT_RANGE:
2396 ret = lysp_stmt_restrs(&pctx, stmt, (struct lysp_restr **)result);
2397 break;
2398 case LY_STMT_LIST:
2399 ret = lysp_stmt_list(&pctx, stmt, NULL, (struct lysp_node **)result);
2400 break;
2401 case LY_STMT_MANDATORY:
2402 ret = lysp_stmt_mandatory(&pctx, stmt, *(uint16_t **)result, exts);
2403 break;
2404 case LY_STMT_MAX_ELEMENTS:
2405 flags = 0;
2406 ret = lysp_stmt_maxelements(&pctx, stmt, *(uint32_t **)result, &flags, exts);
2407 break;
2408 case LY_STMT_MIN_ELEMENTS:
2409 flags = 0;
2410 ret = lysp_stmt_minelements(&pctx, stmt, *(uint32_t **)result, &flags, exts);
2411 break;
2412 case LY_STMT_MODIFIER:
2413 ret = lysp_stmt_type_pattern_modifier(&pctx, stmt, (const char **)result, exts);
2414 break;
2415 case LY_STMT_NOTIFICATION:
2416 ret = lysp_stmt_notif(&pctx, stmt, NULL, (struct lysp_node_notif **)result);
2417 break;
2418 case LY_STMT_ORDERED_BY:
2419 ret = lysp_stmt_orderedby(&pctx, stmt, *(uint16_t **)result, exts);
2420 break;
2421 case LY_STMT_PATH: {
2422 const char *str_path = NULL;
2423
2424 LY_CHECK_RET(lysp_stmt_text_field(&pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02002425 ret = ly_path_parse(ctx->ctx, NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002426 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
2427 lydict_remove(ctx->ctx, str_path);
2428 break;
2429 }
2430 case LY_STMT_PATTERN:
2431 ret = lysp_stmt_type_pattern(&pctx, stmt, (struct lysp_restr **)result);
2432 break;
2433 case LY_STMT_POSITION:
2434 case LY_STMT_VALUE:
2435 flags = 0;
2436 ret = lysp_stmt_type_enum_value_pos(&pctx, stmt, *(int64_t **)result, &flags, exts);
2437 break;
2438 case LY_STMT_PREFIX:
2439 ret = lysp_stmt_text_field(&pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
2440 break;
2441 case LY_STMT_REFINE:
2442 ret = lysp_stmt_refine(&pctx, stmt, (struct lysp_refine **)result);
2443 break;
2444 case LY_STMT_REQUIRE_INSTANCE:
2445 flags = 0;
2446 ret = lysp_stmt_type_reqinstance(&pctx, stmt, *(uint8_t **)result, &flags, exts);
2447 break;
Michal Vasko69730152020-10-09 16:30:07 +02002448 case LY_STMT_STATUS:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002449 ret = lysp_stmt_status(&pctx, stmt, *(uint16_t **)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02002450 break;
Radek Krejci335332a2019-09-05 13:03:35 +02002451 case LY_STMT_TYPE: {
2452 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02002453
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002454 *result = type = calloc(1, sizeof *type);
2455 LY_CHECK_ERR_RET(!type, LOGMEM(ctx->ctx), LY_EMEM);
2456 ret = lysp_stmt_type(&pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02002457 break;
Radek Krejci0f969882020-08-21 16:56:47 +02002458 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002459 case LY_STMT_TYPEDEF:
2460 ret = lysp_stmt_typedef(&pctx, stmt, NULL, (struct lysp_tpdf **)result);
2461 break;
2462 case LY_STMT_USES:
2463 ret = lysp_stmt_uses(&pctx, stmt, NULL, (struct lysp_node **)result);
2464 break;
2465 case LY_STMT_WHEN:
2466 ret = lysp_stmt_when(&pctx, stmt, (struct lysp_when **)result);
2467 break;
Radek Krejci335332a2019-09-05 13:03:35 +02002468 default:
2469 LOGINT(ctx->ctx);
2470 return LY_EINT;
2471 }
2472
Radek Krejciddace2c2021-01-08 11:30:56 +01002473 LOG_LOCBACK(0, 0, 1, 0);
Radek Krejciad5963b2019-09-06 16:03:05 +02002474 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02002475}