blob: ed459def88d7ae983d106fcb63fe45eae5ef474e [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;
Radek Krejci335332a2019-09-05 13:03:35 +0200100 /* TODO (duplicate) e->child = stmt->child; */
101
102 /* get optional argument */
103 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200104 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200105 }
106
107 return LY_SUCCESS;
108}
109
110/**
111 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
112 * description, etc...
113 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100114 * @param[in] ctx parser context.
115 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200116 * @param[in] substmt_index Index of this substatement.
117 * @param[in,out] value Place to store the parsed value.
118 * @param[in] arg Type of the YANG keyword argument (of the value).
119 * @param[in,out] exts Extension instances to add to.
120 *
121 * @return LY_ERR values.
122 */
123static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100124lysp_stmt_text_field(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index,
Radek Krejci0f969882020-08-21 16:56:47 +0200125 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200126{
Radek Krejci335332a2019-09-05 13:03:35 +0200127 if (*value) {
Radek Krejci3972b332021-03-02 16:34:31 +0100128 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200129 return LY_EVALID;
130 }
131
132 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200133 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200134
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100135 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
136 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200137 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100138 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200139 break;
140 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100141 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200142 return LY_EVALID;
143 }
144 }
145 return LY_SUCCESS;
146}
147
148/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200149 * @brief Parse a qname that can have more instances such as if-feature.
150 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100151 * @param[in] ctx parser context.
152 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200153 * @param[in,out] qnames Parsed qnames to add to.
154 * @param[in] arg Type of the expected argument.
155 * @param[in,out] exts Extension instances to add to.
156 *
157 * @return LY_ERR values.
158 */
159static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100160lysp_stmt_qnames(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
Michal Vasko7f45cf22020-10-01 12:49:44 +0200161 struct lysp_qname **qnames, enum yang_arg arg, struct lysp_ext_instance **exts)
162{
163 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200164
165 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
166
167 /* allocate new pointer */
168 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
169 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200170 item->mod = ctx->parsed_mod;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200171
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100172 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
173 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200174 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100175 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200176 break;
177 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100178 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200179 return LY_EVALID;
180 }
181 }
182 return LY_SUCCESS;
183}
184
185/**
Radek Krejci335332a2019-09-05 13:03:35 +0200186 * @brief Parse a generic text field that can have more instances such as base.
187 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100188 * @param[in] ctx parser context.
189 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200190 * @param[in,out] texts Parsed values to add to.
191 * @param[in] arg Type of the expected argument.
192 * @param[in,out] exts Extension instances to add to.
193 *
194 * @return LY_ERR values.
195 */
196static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100197lysp_stmt_text_fields(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200198 const char ***texts, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200199{
200 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200201
202 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
203
204 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100205 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200206 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200207
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100208 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
209 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200210 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100211 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200212 break;
213 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100214 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200215 return LY_EVALID;
216 }
217 }
218 return LY_SUCCESS;
219}
220
221/**
222 * @brief Parse the status statement.
223 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100224 * @param[in] ctx parser context.
225 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200226 * @param[in,out] flags Flags to add to.
227 * @param[in,out] exts Extension instances to add to.
228 *
229 * @return LY_ERR values.
230 */
231static LY_ERR
232lysp_stmt_status(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
233{
234 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200235
236 if (*flags & LYS_STATUS_MASK) {
237 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
238 return LY_EVALID;
239 }
240
241 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
242 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100243 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200244 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100245 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200246 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100247 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200248 *flags |= LYS_STATUS_OBSLT;
249 } else {
250 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
251 return LY_EVALID;
252 }
253
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100254 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
255 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200256 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100257 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200258 break;
259 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100260 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200261 return LY_EVALID;
262 }
263 }
264 return LY_SUCCESS;
265}
266
267/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100268 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200269 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100270 * @param[in] ctx parser context.
271 * @param[in] stmt Source statement data from the parsed extension instance.
272 * @param[in,out] when_p When pointer to parse to.
273 *
274 * @return LY_ERR values.
275 */
276static LY_ERR
277lysp_stmt_when(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
278{
279 LY_ERR ret = LY_SUCCESS;
280 struct lysp_when *when;
281
282 if (*when_p) {
283 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
284 return LY_EVALID;
285 }
286
287 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
288
289 when = calloc(1, sizeof *when);
290 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
291 *when_p = when;
292
293 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
294
295 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
296 switch (child->kw) {
297 case LY_STMT_DESCRIPTION:
298 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
299 break;
300 case LY_STMT_REFERENCE:
301 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
302 break;
303 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100304 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100305 break;
306 default:
307 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "when");
308 return LY_EVALID;
309 }
310 }
311 return ret;
312}
313
314/**
315 * @brief Parse the config statement.
316 *
317 * @param[in] ctx parser context.
318 * @param[in] stmt Source statement data from the parsed extension instance.
319 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200320 * @param[in,out] exts Extension instances to add to.
321 *
322 * @return LY_ERR values.
323 */
324static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100325lysp_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 +0200326{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100327 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200328
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100329 if (*flags & LYS_CONFIG_MASK) {
330 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
331 return LY_EVALID;
332 }
333
334 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
335 arg_len = strlen(stmt->arg);
336 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
337 *flags |= LYS_CONFIG_W;
338 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
339 *flags |= LYS_CONFIG_R;
340 } else {
341 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
342 return LY_EVALID;
343 }
344
345 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
346 switch (child->kw) {
347 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100348 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100349 break;
350 default:
351 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "config");
352 return LY_EVALID;
353 }
354 }
355
356 return LY_SUCCESS;
357}
358
359/**
360 * @brief Parse the mandatory statement.
361 *
362 * @param[in] ctx parser context.
363 * @param[in] stmt Source statement data from the parsed extension instance.
364 * @param[in,out] flags Flags to add to.
365 * @param[in,out] exts Extension instances to add to.
366 *
367 * @return LY_ERR values.
368 */
369static LY_ERR
370lysp_stmt_mandatory(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
371{
372 size_t arg_len;
373
374 if (*flags & LYS_MAND_MASK) {
375 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
376 return LY_EVALID;
377 }
378
379 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
380 arg_len = strlen(stmt->arg);
381 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
382 *flags |= LYS_MAND_TRUE;
383 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
384 *flags |= LYS_MAND_FALSE;
385 } else {
386 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
387 return LY_EVALID;
388 }
389
390 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
391 switch (child->kw) {
392 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100393 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100394 break;
395 default:
396 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "mandatory");
397 return LY_EVALID;
398 }
399 }
400
401 return LY_SUCCESS;
402}
403
404/**
405 * @brief Parse a restriction such as range or length.
406 *
407 * @param[in] ctx parser context.
408 * @param[in] stmt Source statement data from the parsed extension instance.
409 * @param[in,out] exts Extension instances to add to.
410 *
411 * @return LY_ERR values.
412 */
413static LY_ERR
414lysp_stmt_restr(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
415{
Radek Krejci335332a2019-09-05 13:03:35 +0200416 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200417 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200418 restr->arg.mod = ctx->parsed_mod;
Radek Krejci335332a2019-09-05 13:03:35 +0200419
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100420 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
421 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200422 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100423 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200424 break;
425 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100426 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200427 break;
428 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100429 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200430 break;
431 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100432 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200433 break;
434 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100435 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200436 break;
437 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100438 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200439 return LY_EVALID;
440 }
441 }
442 return LY_SUCCESS;
443}
444
445/**
446 * @brief Parse a restriction that can have more instances such as must.
447 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100448 * @param[in] ctx parser context.
449 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200450 * @param[in,out] restrs Restrictions to add to.
451 *
452 * @return LY_ERR values.
453 */
454static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100455lysp_stmt_restrs(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200456{
457 struct lysp_restr *restr;
458
Michal Vaskob36053d2020-03-26 15:49:30 +0100459 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100460 return lysp_stmt_restr(ctx, stmt, restr);
461}
462
463/**
464 * @brief Parse the anydata or anyxml statement.
465 *
466 * @param[in] ctx parser context.
467 * @param[in] stmt Source statement data from the parsed extension instance.
468 * @param[in,out] siblings Siblings to add to.
469 *
470 * @return LY_ERR values.
471 */
472static LY_ERR
473lysp_stmt_any(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
474{
475 struct lysp_node_anydata *any;
476
477 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
478
479 /* create new structure and insert into siblings */
480 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
481
482 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
483 any->parent = parent;
484
485 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
486
487 /* parse substatements */
488 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
489 switch (child->kw) {
490 case LY_STMT_CONFIG:
491 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
492 break;
493 case LY_STMT_DESCRIPTION:
494 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
495 break;
496 case LY_STMT_IF_FEATURE:
497 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
498 break;
499 case LY_STMT_MANDATORY:
500 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
501 break;
502 case LY_STMT_MUST:
503 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
504 break;
505 case LY_STMT_REFERENCE:
506 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
507 break;
508 case LY_STMT_STATUS:
509 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
510 break;
511 case LY_STMT_WHEN:
512 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
513 break;
514 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100515 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100516 break;
517 default:
518 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
519 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(LY_STMT_ANYDATA) : ly_stmt2str(LY_STMT_ANYXML));
520 return LY_EVALID;
521 }
522 }
523
524 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200525}
526
527/**
528 * @brief Parse the value or position statement. Substatement of type enum statement.
529 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100530 * @param[in] ctx parser context.
531 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200532 * @param[in,out] value Value to write to.
533 * @param[in,out] flags Flags to write to.
534 * @param[in,out] exts Extension instances to add to.
535 *
536 * @return LY_ERR values.
537 */
538static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100539lysp_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 +0200540 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200541{
542 size_t arg_len;
543 char *ptr = NULL;
544 long int num = 0;
545 unsigned long int unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200546
547 if (*flags & LYS_SET_VALUE) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100548 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200549 return LY_EVALID;
550 }
551 *flags |= LYS_SET_VALUE;
552
553 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
554
555 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100556 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
557 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
558 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200559 goto error;
560 }
561
562 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100563 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100564 num = strtol(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200565 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100566 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200567 goto error;
568 }
569 } else {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100570 unum = strtoul(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200571 if (unum > UINT64_C(4294967295)) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100572 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200573 goto error;
574 }
575 }
576 /* we have not parsed the whole argument */
577 if ((size_t)(ptr - stmt->arg) != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100578 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200579 goto error;
580 }
581 if (errno == ERANGE) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100582 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200583 goto error;
584 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100585 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200586 *value = num;
587 } else {
588 *value = unum;
589 }
590
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100591 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
592 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200593 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100594 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 +0200595 break;
596 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100597 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200598 return LY_EVALID;
599 }
600 }
601 return LY_SUCCESS;
602
603error:
604 return LY_EVALID;
605}
606
607/**
608 * @brief Parse the enum or bit statement. Substatement of type statement.
609 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100610 * @param[in] ctx parser context.
611 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200612 * @param[in,out] enums Enums or bits to add to.
613 *
614 * @return LY_ERR values.
615 */
616static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100617lysp_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 +0200618{
619 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200620
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100621 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 +0200622
Michal Vaskob36053d2020-03-26 15:49:30 +0100623 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200624
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100625 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +0200626 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
627 } /* else nothing specific for YANG_BIT */
628
Radek Krejci011e4aa2020-09-04 15:22:31 +0200629 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100630 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +0200631
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100632 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
633 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200634 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100635 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200636 break;
637 case LY_STMT_IF_FEATURE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100638 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(stmt->kw));
639 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200640 break;
641 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100642 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200643 break;
644 case LY_STMT_STATUS:
645 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
646 break;
647 case LY_STMT_VALUE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100648 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
649 ly_stmt2str(stmt->kw)), LY_EVALID);
650 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200651 break;
652 case LY_STMT_POSITION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100653 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
654 ly_stmt2str(stmt->kw)), LY_EVALID);
655 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200656 break;
657 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100658 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200659 break;
660 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100661 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200662 return LY_EVALID;
663 }
664 }
665 return LY_SUCCESS;
666}
667
668/**
669 * @brief Parse the fraction-digits statement. Substatement of type statement.
670 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100671 * @param[in] ctx parser context.
672 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200673 * @param[in,out] fracdig Value to write to.
674 * @param[in,out] exts Extension instances to add to.
675 *
676 * @return LY_ERR values.
677 */
678static LY_ERR
679lysp_stmt_type_fracdigits(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig, struct lysp_ext_instance **exts)
680{
681 char *ptr;
682 size_t arg_len;
683 unsigned long int num;
Radek Krejci335332a2019-09-05 13:03:35 +0200684
685 if (*fracdig) {
686 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
687 return LY_EVALID;
688 }
689
690 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
691 arg_len = strlen(stmt->arg);
692 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
693 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
694 return LY_EVALID;
695 }
696
697 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100698 num = strtoul(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200699 /* we have not parsed the whole argument */
700 if ((size_t)(ptr - stmt->arg) != arg_len) {
701 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
702 return LY_EVALID;
703 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100704 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200705 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
706 return LY_EVALID;
707 }
708 *fracdig = num;
709
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100710 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
711 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200712 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100713 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200714 break;
715 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100716 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +0200717 return LY_EVALID;
718 }
719 }
720 return LY_SUCCESS;
721}
722
723/**
724 * @brief Parse the require-instance statement. Substatement of type statement.
725 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100726 * @param[in] ctx parser context.
727 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200728 * @param[in,out] reqinst Value to write to.
729 * @param[in,out] flags Flags to write to.
730 * @param[in,out] exts Extension instances to add to.
731 *
732 * @return LY_ERR values.
733 */
734static LY_ERR
735lysp_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 +0200736 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200737{
738 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200739
740 if (*flags & LYS_SET_REQINST) {
741 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
742 return LY_EVALID;
743 }
744 *flags |= LYS_SET_REQINST;
745
746 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
747 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100748 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200749 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100750 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200751 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
752 return LY_EVALID;
753 }
754
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100755 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
756 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200757 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100758 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200759 break;
760 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100761 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +0200762 return LY_EVALID;
763 }
764 }
765 return LY_SUCCESS;
766}
767
768/**
769 * @brief Parse the modifier statement. Substatement of type pattern statement.
770 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100771 * @param[in] ctx parser context.
772 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200773 * @param[in,out] pat Value to write to.
774 * @param[in,out] exts Extension instances to add to.
775 *
776 * @return LY_ERR values.
777 */
778static LY_ERR
779lysp_stmt_type_pattern_modifier(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, const char **pat, struct lysp_ext_instance **exts)
780{
781 size_t arg_len;
782 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +0200783
Radek Krejcif13b87b2020-12-01 22:02:17 +0100784 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +0200785 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
786 return LY_EVALID;
787 }
788
789 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
790 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100791 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200792 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
793 return LY_EVALID;
794 }
795
796 /* replace the value in the dictionary */
797 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100798 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200799 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100800 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +0200801
Radek Krejcif13b87b2020-12-01 22:02:17 +0100802 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
803 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200804 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +0200805
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100806 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
807 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200808 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100809 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200810 break;
811 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100812 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +0200813 return LY_EVALID;
814 }
815 }
816 return LY_SUCCESS;
817}
818
819/**
820 * @brief Parse the pattern statement. Substatement of type statement.
821 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100822 * @param[in] ctx parser context.
823 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200824 * @param[in,out] patterns Restrictions to add to.
825 *
826 * @return LY_ERR values.
827 */
828static LY_ERR
829lysp_stmt_type_pattern(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
830{
831 char *buf;
832 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200833 struct lysp_restr *restr;
834
835 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +0100836 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200837 arg_len = strlen(stmt->arg);
838
839 /* add special meaning first byte */
840 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100841 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200842 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100843 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +0200844 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +0200845 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200846 restr->arg.mod = ctx->parsed_mod;
Radek Krejci335332a2019-09-05 13:03:35 +0200847
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100848 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
849 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200850 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100851 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200852 break;
853 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100854 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200855 break;
856 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100857 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200858 break;
859 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100860 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200861 break;
862 case LY_STMT_MODIFIER:
863 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +0200864 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200865 break;
866 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100867 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200868 break;
869 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100870 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +0200871 return LY_EVALID;
872 }
873 }
874 return LY_SUCCESS;
875}
876
877/**
878 * @brief Parse the type statement.
879 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100880 * @param[in] ctx parser context.
881 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200882 * @param[in,out] type Type to wrote to.
883 *
884 * @return LY_ERR values.
885 */
886static LY_ERR
887lysp_stmt_type(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
888{
889 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +0200890 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +0200891 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +0200892
893 if (type->name) {
894 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
895 return LY_EVALID;
896 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100897
898 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200899 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200900 type->pmod = ctx->parsed_mod;
Radek Krejci335332a2019-09-05 13:03:35 +0200901
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100902 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
903 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200904 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100905 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200906 type->flags |= LYS_SET_BASE;
907 break;
908 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100909 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +0200910 type->flags |= LYS_SET_BIT;
911 break;
912 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100913 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +0200914 type->flags |= LYS_SET_ENUM;
915 break;
916 case LY_STMT_FRACTION_DIGITS:
917 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
918 type->flags |= LYS_SET_FRDIGITS;
919 break;
920 case LY_STMT_LENGTH:
921 if (type->length) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100922 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200923 return LY_EVALID;
924 }
925 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100926 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200927
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100928 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +0200929 type->flags |= LYS_SET_LENGTH;
930 break;
931 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100932 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vasko6b26e742020-07-17 15:02:10 +0200933 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
Michal Vasko69730152020-10-09 16:30:07 +0200934 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200935 lydict_remove(PARSER_CTX(ctx), str_path);
936 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +0200937 type->flags |= LYS_SET_PATH;
938 break;
939 case LY_STMT_PATTERN:
940 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
941 type->flags |= LYS_SET_PATTERN;
942 break;
943 case LY_STMT_RANGE:
944 if (type->range) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100945 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200946 return LY_EVALID;
947 }
948 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100949 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200950
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100951 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +0200952 type->flags |= LYS_SET_RANGE;
953 break;
954 case LY_STMT_REQUIRE_INSTANCE:
955 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100956 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +0200957 break;
958 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +0100959 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200960 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
961 type->flags |= LYS_SET_TYPE;
962 break;
963 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100964 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200965 break;
966 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100967 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +0200968 return LY_EVALID;
969 }
970 }
971 return LY_SUCCESS;
972}
973
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100974/**
975 * @brief Parse the leaf statement.
976 *
977 * @param[in] ctx parser context.
978 * @param[in] stmt Source statement data from the parsed extension instance.
979 * @param[in] parent Parent node to connect to (not into).
980 * @param[in,out] siblings Siblings to add to.
981 *
982 * @return LY_ERR values.
983 */
984static LY_ERR
985lysp_stmt_leaf(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
986{
987 struct lysp_node_leaf *leaf;
988
989 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
990
991 /* create new leaf structure */
992 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
993 leaf->nodetype = LYS_LEAF;
994 leaf->parent = parent;
995
996 /* get name */
997 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
998
999 /* parse substatements */
1000 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1001 switch (child->kw) {
1002 case LY_STMT_CONFIG:
1003 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1004 break;
1005 case LY_STMT_DEFAULT:
1006 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dflt.str, Y_STR_ARG, &leaf->exts));
1007 leaf->dflt.mod = ctx->parsed_mod;
1008 break;
1009 case LY_STMT_DESCRIPTION:
1010 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1011 break;
1012 case LY_STMT_IF_FEATURE:
1013 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1014 break;
1015 case LY_STMT_MANDATORY:
1016 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1017 break;
1018 case LY_STMT_MUST:
1019 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1020 break;
1021 case LY_STMT_REFERENCE:
1022 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1023 break;
1024 case LY_STMT_STATUS:
1025 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1026 break;
1027 case LY_STMT_TYPE:
1028 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1029 break;
1030 case LY_STMT_UNITS:
1031 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1032 break;
1033 case LY_STMT_WHEN:
1034 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1035 break;
1036 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001037 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001038 break;
1039 default:
1040 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "leaf");
1041 return LY_EVALID;
1042 }
1043 }
1044
1045 /* mandatory substatements */
1046 if (!leaf->type.name) {
1047 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1048 return LY_EVALID;
1049 }
1050
1051 return LY_SUCCESS;
1052}
1053
1054/**
1055 * @brief Parse the max-elements statement.
1056 *
1057 * @param[in] ctx parser context.
1058 * @param[in] stmt Source statement data from the parsed extension instance.
1059 * @param[in,out] max Value to write to.
1060 * @param[in,out] flags Flags to write to.
1061 * @param[in,out] exts Extension instances to add to.
1062 *
1063 * @return LY_ERR values.
1064 */
1065static LY_ERR
1066lysp_stmt_maxelements(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
1067 uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
1068{
1069 size_t arg_len;
1070 char *ptr;
1071 unsigned long int num;
1072
1073 if (*flags & LYS_SET_MAX) {
1074 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1075 return LY_EVALID;
1076 }
1077 *flags |= LYS_SET_MAX;
1078
1079 /* get value */
1080 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1081 arg_len = strlen(stmt->arg);
1082
1083 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1084 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1085 return LY_EVALID;
1086 }
1087
1088 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1089 errno = 0;
1090 num = strtoul(stmt->arg, &ptr, LY_BASE_DEC);
1091 /* we have not parsed the whole argument */
1092 if ((size_t)(ptr - stmt->arg) != arg_len) {
1093 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1094 return LY_EVALID;
1095 }
1096 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1097 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1098 return LY_EVALID;
1099 }
1100
1101 *max = num;
1102 } else {
1103 /* unbounded */
1104 *max = 0;
1105 }
1106
1107 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1108 switch (child->kw) {
1109 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001110 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001111 break;
1112 default:
1113 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "max-elements");
1114 return LY_EVALID;
1115 }
1116 }
1117
1118 return LY_SUCCESS;
1119}
1120
1121/**
1122 * @brief Parse the min-elements statement.
1123 *
1124 * @param[in] ctx parser context.
1125 * @param[in] stmt Source statement data from the parsed extension instance.
1126 * @param[in,out] min Value to write to.
1127 * @param[in,out] flags Flags to write to.
1128 * @param[in,out] exts Extension instances to add to.
1129 *
1130 * @return LY_ERR values.
1131 */
1132static LY_ERR
1133lysp_stmt_minelements(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
1134 uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
1135{
1136 size_t arg_len;
1137 char *ptr;
1138 unsigned long int num;
1139
1140 if (*flags & LYS_SET_MIN) {
1141 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
1142 return LY_EVALID;
1143 }
1144 *flags |= LYS_SET_MIN;
1145
1146 /* get value */
1147 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1148 arg_len = strlen(stmt->arg);
1149
1150 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
1151 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1152 return LY_EVALID;
1153 }
1154
1155 errno = 0;
1156 num = strtoul(stmt->arg, &ptr, LY_BASE_DEC);
1157 /* we have not parsed the whole argument */
1158 if ((size_t)(ptr - stmt->arg) != arg_len) {
1159 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1160 return LY_EVALID;
1161 }
1162 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1163 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
1164 return LY_EVALID;
1165 }
1166 *min = num;
1167
1168 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1169 switch (child->kw) {
1170 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001171 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001172 break;
1173 default:
1174 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "min-elements");
1175 return LY_EVALID;
1176 }
1177 }
1178
1179 return LY_SUCCESS;
1180}
1181
1182/**
1183 * @brief Parse the ordered-by statement.
1184 *
1185 * @param[in] ctx parser context.
1186 * @param[in] stmt Source statement data from the parsed extension instance.
1187 * @param[in,out] flags Flags to write to.
1188 * @param[in,out] exts Extension instances to add to.
1189 *
1190 * @return LY_ERR values.
1191 */
1192static LY_ERR
1193lysp_stmt_orderedby(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1194{
1195 size_t arg_len;
1196
1197 if (*flags & LYS_ORDBY_MASK) {
1198 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
1199 return LY_EVALID;
1200 }
1201
1202 /* get value */
1203 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1204 arg_len = strlen(stmt->arg);
1205 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
1206 *flags |= LYS_MAND_TRUE;
1207 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
1208 *flags |= LYS_MAND_FALSE;
1209 } else {
1210 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
1211 return LY_EVALID;
1212 }
1213
1214 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1215 switch (child->kw) {
1216 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001217 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001218 break;
1219 default:
1220 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "ordered-by");
1221 return LY_EVALID;
1222 }
1223 }
1224
1225 return LY_SUCCESS;
1226}
1227
1228/**
1229 * @brief Parse the leaf-list statement.
1230 *
1231 * @param[in] ctx parser context.
1232 * @param[in] stmt Source statement data from the parsed extension instance.
1233 * @param[in] parent Parent node to connect to (not into).
1234 * @param[in,out] siblings Siblings to add to.
1235 *
1236 * @return LY_ERR values.
1237 */
1238static LY_ERR
1239lysp_stmt_leaflist(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
1240{
1241 struct lysp_node_leaflist *llist;
1242
1243 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1244
1245 /* create new leaf-list structure */
1246 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
1247 llist->nodetype = LYS_LEAFLIST;
1248 llist->parent = parent;
1249
1250 /* get name */
1251 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
1252
1253 /* parse substatements */
1254 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1255 switch (child->kw) {
1256 case LY_STMT_CONFIG:
1257 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
1258 break;
1259 case LY_STMT_DEFAULT:
1260 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
1261 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
1262 break;
1263 case LY_STMT_DESCRIPTION:
1264 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
1265 break;
1266 case LY_STMT_IF_FEATURE:
1267 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
1268 break;
1269 case LY_STMT_MAX_ELEMENTS:
1270 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
1271 break;
1272 case LY_STMT_MIN_ELEMENTS:
1273 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
1274 break;
1275 case LY_STMT_MUST:
1276 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
1277 break;
1278 case LY_STMT_ORDERED_BY:
1279 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
1280 break;
1281 case LY_STMT_REFERENCE:
1282 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
1283 break;
1284 case LY_STMT_STATUS:
1285 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
1286 break;
1287 case LY_STMT_TYPE:
1288 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
1289 break;
1290 case LY_STMT_UNITS:
1291 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
1292 break;
1293 case LY_STMT_WHEN:
1294 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
1295 break;
1296 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001297 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001298 break;
1299 default:
1300 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "llist");
1301 return LY_EVALID;
1302 }
1303 }
1304
1305 /* mandatory substatements */
1306 if (!llist->type.name) {
1307 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
1308 return LY_EVALID;
1309 }
1310
1311 return LY_SUCCESS;
1312}
1313
1314/**
1315 * @brief Parse the refine statement.
1316 *
1317 * @param[in] ctx parser context.
1318 * @param[in] stmt Source statement data from the parsed extension instance.
1319 * @param[in,out] refines Refines to add to.
1320 *
1321 * @return LY_ERR values.
1322 */
1323static LY_ERR
1324lysp_stmt_refine(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
1325{
1326 struct lysp_refine *rf;
1327
1328 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1329
1330 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
1331
1332 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
1333
1334 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1335 switch (child->kw) {
1336 case LY_STMT_CONFIG:
1337 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
1338 break;
1339 case LY_STMT_DEFAULT:
1340 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
1341 break;
1342 case LY_STMT_DESCRIPTION:
1343 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
1344 break;
1345 case LY_STMT_IF_FEATURE:
1346 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
1347 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
1348 break;
1349 case LY_STMT_MAX_ELEMENTS:
1350 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
1351 break;
1352 case LY_STMT_MIN_ELEMENTS:
1353 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
1354 break;
1355 case LY_STMT_MUST:
1356 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
1357 break;
1358 case LY_STMT_MANDATORY:
1359 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
1360 break;
1361 case LY_STMT_REFERENCE:
1362 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
1363 break;
1364 case LY_STMT_PRESENCE:
1365 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
1366 break;
1367 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001368 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001369 break;
1370 default:
1371 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "refine");
1372 return LY_EVALID;
1373 }
1374 }
1375
1376 return LY_SUCCESS;
1377}
1378
1379/**
1380 * @brief Parse the typedef statement.
1381 *
1382 * @param[in] ctx parser context.
1383 * @param[in] stmt Source statement data from the parsed extension instance.
1384 * @param[in] parent Parent node to connect to (not into).
1385 * @param[in,out] typedefs Typedefs to add to.
1386 *
1387 * @return LY_ERR values.
1388 */
1389static LY_ERR
1390lysp_stmt_typedef(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_tpdf **typedefs)
1391{
1392 struct lysp_tpdf *tpdf;
1393
1394 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1395
1396 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
1397
1398 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
1399
1400 /* parse substatements */
1401 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1402 switch (child->kw) {
1403 case LY_STMT_DEFAULT:
1404 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dflt.str, Y_STR_ARG, &tpdf->exts));
1405 tpdf->dflt.mod = ctx->parsed_mod;
1406 break;
1407 case LY_STMT_DESCRIPTION:
1408 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
1409 break;
1410 case LY_STMT_REFERENCE:
1411 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
1412 break;
1413 case LY_STMT_STATUS:
1414 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
1415 break;
1416 case LY_STMT_TYPE:
1417 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
1418 break;
1419 case LY_STMT_UNITS:
1420 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
1421 break;
1422 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001423 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001424 break;
1425 default:
1426 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "typedef");
1427 return LY_EVALID;
1428 }
1429 }
1430
1431 /* mandatory substatements */
1432 if (!tpdf->type.name) {
1433 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
1434 return LY_EVALID;
1435 }
1436
1437 /* store data for collision check */
1438 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
1439 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
1440 }
1441
1442 return LY_SUCCESS;
1443}
1444
1445/**
1446 * @brief Parse the input or output statement.
1447 *
1448 * @param[in] ctx parser context.
1449 * @param[in] stmt Source statement data from the parsed extension instance.
1450 * @param[in] parent Parent node to connect to (not into).
1451 * @param[in,out] inout_p Input/output pointer to write to.
1452 *
1453 * @return LY_ERR values.
1454 */
1455static LY_ERR
1456lysp_stmt_inout(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
1457 struct lysp_node_action_inout *inout_p)
1458{
1459 if (inout_p->nodetype) {
1460 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
1461 return LY_EVALID;
1462 }
1463
1464 /* initiate structure */
1465 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
1466 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
1467 inout_p->parent = parent;
1468
1469 /* parse substatements */
1470 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1471 switch (child->kw) {
1472 case LY_STMT_ANYDATA:
1473 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(stmt->kw));
1474 /* fall through */
1475 case LY_STMT_ANYXML:
1476 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
1477 break;
1478 case LY_STMT_CHOICE:
1479 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
1480 break;
1481 case LY_STMT_CONTAINER:
1482 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
1483 break;
1484 case LY_STMT_LEAF:
1485 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
1486 break;
1487 case LY_STMT_LEAF_LIST:
1488 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
1489 break;
1490 case LY_STMT_LIST:
1491 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
1492 break;
1493 case LY_STMT_USES:
1494 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
1495 break;
1496 case LY_STMT_TYPEDEF:
1497 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
1498 break;
1499 case LY_STMT_MUST:
1500 PARSER_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(stmt->kw));
1501 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
1502 break;
1503 case LY_STMT_GROUPING:
1504 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
1505 break;
1506 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001507 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001508 break;
1509 default:
1510 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
1511 return LY_EVALID;
1512 }
1513 }
1514
1515 if (!inout_p->child) {
1516 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(stmt->kw));
1517 return LY_EVALID;
1518 }
1519
1520 return LY_SUCCESS;
1521}
1522
1523/**
1524 * @brief Parse the action statement.
1525 *
1526 * @param[in] ctx parser context.
1527 * @param[in] stmt Source statement data from the parsed extension instance.
1528 * @param[in] parent Parent node to connect to (not into).
1529 * @param[in,out] actions Actions to add to.
1530 *
1531 * @return LY_ERR values.
1532 */
1533static LY_ERR
1534lysp_stmt_action(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node_action **actions)
1535{
1536 struct lysp_node_action *act;
1537
1538 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1539
1540 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
1541
1542 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
1543 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
1544 act->parent = parent;
1545
1546 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1547 switch (child->kw) {
1548 case LY_STMT_DESCRIPTION:
1549 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
1550 break;
1551 case LY_STMT_IF_FEATURE:
1552 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
1553 break;
1554 case LY_STMT_REFERENCE:
1555 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
1556 break;
1557 case LY_STMT_STATUS:
1558 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
1559 break;
1560
1561 case LY_STMT_INPUT:
1562 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
1563 break;
1564 case LY_STMT_OUTPUT:
1565 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
1566 break;
1567
1568 case LY_STMT_TYPEDEF:
1569 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
1570 break;
1571 case LY_STMT_GROUPING:
1572 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
1573 break;
1574 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001575 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 +01001576 break;
1577 default:
1578 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), parent ? "action" : "rpc");
1579 return LY_EVALID;
1580 }
1581 }
1582
1583 /* always initialize inout, they are technically present (needed for later deviations/refines) */
1584 if (!act->input.nodetype) {
1585 act->input.nodetype = LYS_INPUT;
1586 act->input.parent = &act->node;
1587 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
1588 }
1589 if (!act->output.nodetype) {
1590 act->output.nodetype = LYS_OUTPUT;
1591 act->output.parent = &act->node;
1592 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
1593 }
1594
1595 return LY_SUCCESS;
1596}
1597
1598/**
1599 * @brief Parse the notification statement.
1600 *
1601 * @param[in] ctx parser context.
1602 * @param[in] stmt Source statement data from the parsed extension instance.
1603 * @param[in] parent Parent node to connect to (not into).
1604 * @param[in,out] notifs Notifications to add to.
1605 *
1606 * @return LY_ERR values.
1607 */
1608static LY_ERR
1609lysp_stmt_notif(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node_notif **notifs)
1610{
1611 struct lysp_node_notif *notif;
1612
1613 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1614
1615 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
1616
1617 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
1618 notif->nodetype = LYS_NOTIF;
1619 notif->parent = parent;
1620
1621 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1622 switch (child->kw) {
1623 case LY_STMT_DESCRIPTION:
1624 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
1625 break;
1626 case LY_STMT_IF_FEATURE:
1627 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
1628 break;
1629 case LY_STMT_REFERENCE:
1630 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
1631 break;
1632 case LY_STMT_STATUS:
1633 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
1634 break;
1635
1636 case LY_STMT_ANYDATA:
1637 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
1638 /* fall through */
1639 case LY_STMT_ANYXML:
1640 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
1641 break;
1642 case LY_STMT_CHOICE:
1643 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
1644 break;
1645 case LY_STMT_CONTAINER:
1646 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
1647 break;
1648 case LY_STMT_LEAF:
1649 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
1650 break;
1651 case LY_STMT_LEAF_LIST:
1652 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
1653 break;
1654 case LY_STMT_LIST:
1655 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
1656 break;
1657 case LY_STMT_USES:
1658 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
1659 break;
1660
1661 case LY_STMT_MUST:
1662 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
1663 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
1664 break;
1665 case LY_STMT_TYPEDEF:
1666 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
1667 break;
1668 case LY_STMT_GROUPING:
1669 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
1670 break;
1671 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001672 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001673 break;
1674 default:
1675 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "notification");
1676 return LY_EVALID;
1677 }
1678 }
1679
1680 return LY_SUCCESS;
1681}
1682
1683/**
1684 * @brief Parse the grouping statement.
1685 *
1686 * @param[in] ctx parser context.
1687 * @param[in] stmt Source statement data from the parsed extension instance.
1688 * @param[in] parent Parent node to connect to (not into).
1689 * @param[in,out] groupings Groupings to add to.
1690 *
1691 * @return LY_ERR values.
1692 */
1693static LY_ERR
1694lysp_stmt_grouping(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node_grp **groupings)
1695{
1696 struct lysp_node_grp *grp;
1697
1698 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1699
1700 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
1701
1702 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
1703 grp->nodetype = LYS_GROUPING;
1704 grp->parent = parent;
1705
1706 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1707 switch (child->kw) {
1708 case LY_STMT_DESCRIPTION:
1709 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
1710 break;
1711 case LY_STMT_REFERENCE:
1712 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
1713 break;
1714 case LY_STMT_STATUS:
1715 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
1716 break;
1717
1718 case LY_STMT_ANYDATA:
1719 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
1720 /* fall through */
1721 case LY_STMT_ANYXML:
1722 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
1723 break;
1724 case LY_STMT_CHOICE:
1725 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
1726 break;
1727 case LY_STMT_CONTAINER:
1728 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
1729 break;
1730 case LY_STMT_LEAF:
1731 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
1732 break;
1733 case LY_STMT_LEAF_LIST:
1734 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
1735 break;
1736 case LY_STMT_LIST:
1737 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
1738 break;
1739 case LY_STMT_USES:
1740 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
1741 break;
1742
1743 case LY_STMT_TYPEDEF:
1744 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
1745 break;
1746 case LY_STMT_ACTION:
1747 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
1748 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
1749 break;
1750 case LY_STMT_GROUPING:
1751 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
1752 break;
1753 case LY_STMT_NOTIFICATION:
1754 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
1755 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
1756 break;
1757 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001758 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001759 break;
1760 default:
1761 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "grouping");
1762 return LY_EVALID;
1763 }
1764 }
1765
1766 return LY_SUCCESS;
1767}
1768
1769/**
1770 * @brief Parse the augment statement.
1771 *
1772 * @param[in] ctx parser context.
1773 * @param[in] stmt Source statement data from the parsed extension instance.
1774 * @param[in] parent Parent node to connect to (not into).
1775 * @param[in,out] augments Augments to add to.
1776 *
1777 * @return LY_ERR values.
1778 */
1779static LY_ERR
1780lysp_stmt_augment(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node_augment **augments)
1781{
1782 struct lysp_node_augment *aug;
1783
1784 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1785
1786 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
1787
1788 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
1789 aug->nodetype = LYS_AUGMENT;
1790 aug->parent = parent;
1791
1792 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1793 switch (child->kw) {
1794 case LY_STMT_DESCRIPTION:
1795 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
1796 break;
1797 case LY_STMT_IF_FEATURE:
1798 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
1799 break;
1800 case LY_STMT_REFERENCE:
1801 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
1802 break;
1803 case LY_STMT_STATUS:
1804 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
1805 break;
1806 case LY_STMT_WHEN:
1807 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
1808 break;
1809
1810 case LY_STMT_ANYDATA:
1811 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
1812 /* fall through */
1813 case LY_STMT_ANYXML:
1814 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
1815 break;
1816 case LY_STMT_CASE:
1817 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
1818 break;
1819 case LY_STMT_CHOICE:
1820 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
1821 break;
1822 case LY_STMT_CONTAINER:
1823 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
1824 break;
1825 case LY_STMT_LEAF:
1826 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
1827 break;
1828 case LY_STMT_LEAF_LIST:
1829 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
1830 break;
1831 case LY_STMT_LIST:
1832 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
1833 break;
1834 case LY_STMT_USES:
1835 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
1836 break;
1837
1838 case LY_STMT_ACTION:
1839 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
1840 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
1841 break;
1842 case LY_STMT_NOTIFICATION:
1843 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
1844 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
1845 break;
1846 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001847 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001848 break;
1849 default:
1850 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "augment");
1851 return LY_EVALID;
1852 }
1853 }
1854
1855 return LY_SUCCESS;
1856}
1857
1858/**
1859 * @brief Parse the uses statement.
1860 *
1861 * @param[in] ctx parser context.
1862 * @param[in] stmt Source statement data from the parsed extension instance.
1863 * @param[in] parent Parent node to connect to (not into).
1864 * @param[in,out] siblings Siblings to add to.
1865 *
1866 * @return LY_ERR values.
1867 */
1868static LY_ERR
1869lysp_stmt_uses(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
1870{
1871 struct lysp_node_uses *uses;
1872
1873 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1874
1875 /* create uses structure */
1876 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
1877
1878 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
1879 uses->nodetype = LYS_USES;
1880 uses->parent = parent;
1881
1882 /* parse substatements */
1883 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1884 switch (child->kw) {
1885 case LY_STMT_DESCRIPTION:
1886 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
1887 break;
1888 case LY_STMT_IF_FEATURE:
1889 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
1890 break;
1891 case LY_STMT_REFERENCE:
1892 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
1893 break;
1894 case LY_STMT_STATUS:
1895 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
1896 break;
1897 case LY_STMT_WHEN:
1898 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
1899 break;
1900
1901 case LY_STMT_REFINE:
1902 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
1903 break;
1904 case LY_STMT_AUGMENT:
1905 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
1906 break;
1907 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001908 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001909 break;
1910 default:
1911 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "uses");
1912 return LY_EVALID;
1913 }
1914 }
1915
1916 return LY_SUCCESS;
1917}
1918
1919/**
1920 * @brief Parse the case statement.
1921 *
1922 * @param[in] ctx parser context.
1923 * @param[in] stmt Source statement data from the parsed extension instance.
1924 * @param[in] parent Parent node to connect to (not into).
1925 * @param[in,out] siblings Siblings to add to.
1926 *
1927 * @return LY_ERR values.
1928 */
1929static LY_ERR
1930lysp_stmt_case(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
1931{
1932 struct lysp_node_case *cas;
1933
1934 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1935
1936 /* create new case structure */
1937 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
1938
1939 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
1940 cas->nodetype = LYS_CASE;
1941 cas->parent = parent;
1942
1943 /* parse substatements */
1944 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1945 switch (child->kw) {
1946 case LY_STMT_DESCRIPTION:
1947 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
1948 break;
1949 case LY_STMT_IF_FEATURE:
1950 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
1951 break;
1952 case LY_STMT_REFERENCE:
1953 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
1954 break;
1955 case LY_STMT_STATUS:
1956 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
1957 break;
1958 case LY_STMT_WHEN:
1959 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
1960 break;
1961
1962 case LY_STMT_ANYDATA:
1963 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
1964 /* fall through */
1965 case LY_STMT_ANYXML:
1966 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
1967 break;
1968 case LY_STMT_CHOICE:
1969 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
1970 break;
1971 case LY_STMT_CONTAINER:
1972 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
1973 break;
1974 case LY_STMT_LEAF:
1975 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
1976 break;
1977 case LY_STMT_LEAF_LIST:
1978 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
1979 break;
1980 case LY_STMT_LIST:
1981 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
1982 break;
1983 case LY_STMT_USES:
1984 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
1985 break;
1986 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001987 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001988 break;
1989 default:
1990 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "case");
1991 return LY_EVALID;
1992 }
1993 }
1994 return LY_SUCCESS;
1995}
1996
1997/**
1998 * @brief Parse the choice statement.
1999 *
2000 * @param[in] ctx parser context.
2001 * @param[in] stmt Source statement data from the parsed extension instance.
2002 * @param[in] parent Parent node to connect to (not into).
2003 * @param[in,out] siblings Siblings to add to.
2004 *
2005 * @return LY_ERR values.
2006 */
2007static LY_ERR
2008lysp_stmt_choice(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
2009{
2010 struct lysp_node_choice *choice;
2011
2012 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2013
2014 /* create new choice structure */
2015 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2016
2017 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2018 choice->nodetype = LYS_CHOICE;
2019 choice->parent = parent;
2020
2021 /* parse substatements */
2022 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2023 switch (child->kw) {
2024 case LY_STMT_CONFIG:
2025 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2026 break;
2027 case LY_STMT_DESCRIPTION:
2028 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2029 break;
2030 case LY_STMT_IF_FEATURE:
2031 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2032 break;
2033 case LY_STMT_MANDATORY:
2034 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2035 break;
2036 case LY_STMT_REFERENCE:
2037 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2038 break;
2039 case LY_STMT_STATUS:
2040 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2041 break;
2042 case LY_STMT_WHEN:
2043 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2044 break;
2045 case LY_STMT_DEFAULT:
2046 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dflt.str, Y_PREF_IDENTIF_ARG, &choice->exts));
2047 choice->dflt.mod = ctx->parsed_mod;
2048 break;
2049 case LY_STMT_ANYDATA:
2050 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2051 /* fall through */
2052 case LY_STMT_ANYXML:
2053 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2054 break;
2055 case LY_STMT_CASE:
2056 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2057 break;
2058 case LY_STMT_CHOICE:
2059 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2060 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2061 break;
2062 case LY_STMT_CONTAINER:
2063 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2064 break;
2065 case LY_STMT_LEAF:
2066 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2067 break;
2068 case LY_STMT_LEAF_LIST:
2069 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2070 break;
2071 case LY_STMT_LIST:
2072 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2073 break;
2074 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002075 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002076 break;
2077 default:
2078 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "choice");
2079 return LY_EVALID;
2080 }
2081 }
2082 return LY_SUCCESS;
2083}
2084
2085/**
2086 * @brief Parse the container statement.
2087 *
2088 * @param[in] ctx parser context.
2089 * @param[in] stmt Source statement data from the parsed extension instance.
2090 * @param[in] parent Parent node to connect to (not into).
2091 * @param[in,out] siblings Siblings to add to.
2092 *
2093 * @return LY_ERR values.
2094 */
2095static LY_ERR
2096lysp_stmt_container(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
2097{
2098 struct lysp_node_container *cont;
2099
2100 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2101
2102 /* create new container structure */
2103 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2104
2105 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2106 cont->nodetype = LYS_CONTAINER;
2107 cont->parent = parent;
2108
2109 /* parse substatements */
2110 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2111 switch (child->kw) {
2112 case LY_STMT_CONFIG:
2113 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
2114 break;
2115 case LY_STMT_DESCRIPTION:
2116 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
2117 break;
2118 case LY_STMT_IF_FEATURE:
2119 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
2120 break;
2121 case LY_STMT_REFERENCE:
2122 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
2123 break;
2124 case LY_STMT_STATUS:
2125 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
2126 break;
2127 case LY_STMT_WHEN:
2128 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
2129 break;
2130 case LY_STMT_PRESENCE:
2131 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
2132 break;
2133 case LY_STMT_ANYDATA:
2134 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
2135 /* fall through */
2136 case LY_STMT_ANYXML:
2137 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
2138 break;
2139 case LY_STMT_CHOICE:
2140 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
2141 break;
2142 case LY_STMT_CONTAINER:
2143 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
2144 break;
2145 case LY_STMT_LEAF:
2146 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
2147 break;
2148 case LY_STMT_LEAF_LIST:
2149 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
2150 break;
2151 case LY_STMT_LIST:
2152 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
2153 break;
2154 case LY_STMT_USES:
2155 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
2156 break;
2157
2158 case LY_STMT_TYPEDEF:
2159 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
2160 break;
2161 case LY_STMT_MUST:
2162 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
2163 break;
2164 case LY_STMT_ACTION:
2165 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
2166 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
2167 break;
2168 case LY_STMT_GROUPING:
2169 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
2170 break;
2171 case LY_STMT_NOTIFICATION:
2172 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
2173 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
2174 break;
2175 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002176 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002177 break;
2178 default:
2179 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "container");
2180 return LY_EVALID;
2181 }
2182 }
2183
2184 return LY_SUCCESS;
2185}
2186
2187/**
2188 * @brief Parse the list statement.
2189 *
2190 * @param[in] ctx parser context.
2191 * @param[in] stmt Source statement data from the parsed extension instance.
2192 * @param[in] parent Parent node to connect to (not into).
2193 * @param[in,out] siblings Siblings to add to.
2194 *
2195 * @return LY_ERR values.
2196 */
2197static LY_ERR
2198lysp_stmt_list(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
2199{
2200 struct lysp_node_list *list;
2201
2202 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2203
2204 /* create new list structure */
2205 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
2206
2207 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
2208 list->nodetype = LYS_LIST;
2209 list->parent = parent;
2210
2211 /* parse substatements */
2212 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2213 switch (child->kw) {
2214 case LY_STMT_CONFIG:
2215 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
2216 break;
2217 case LY_STMT_DESCRIPTION:
2218 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
2219 break;
2220 case LY_STMT_IF_FEATURE:
2221 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
2222 break;
2223 case LY_STMT_REFERENCE:
2224 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
2225 break;
2226 case LY_STMT_STATUS:
2227 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
2228 break;
2229 case LY_STMT_WHEN:
2230 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
2231 break;
2232 case LY_STMT_KEY:
2233 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
2234 break;
2235 case LY_STMT_MAX_ELEMENTS:
2236 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
2237 break;
2238 case LY_STMT_MIN_ELEMENTS:
2239 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
2240 break;
2241 case LY_STMT_ORDERED_BY:
2242 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
2243 break;
2244 case LY_STMT_UNIQUE:
2245 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
2246 break;
2247
2248 case LY_STMT_ANYDATA:
2249 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
2250 /* fall through */
2251 case LY_STMT_ANYXML:
2252 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
2253 break;
2254 case LY_STMT_CHOICE:
2255 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
2256 break;
2257 case LY_STMT_CONTAINER:
2258 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
2259 break;
2260 case LY_STMT_LEAF:
2261 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
2262 break;
2263 case LY_STMT_LEAF_LIST:
2264 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
2265 break;
2266 case LY_STMT_LIST:
2267 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
2268 break;
2269 case LY_STMT_USES:
2270 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
2271 break;
2272
2273 case LY_STMT_TYPEDEF:
2274 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
2275 break;
2276 case LY_STMT_MUST:
2277 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
2278 break;
2279 case LY_STMT_ACTION:
2280 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
2281 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
2282 break;
2283 case LY_STMT_GROUPING:
2284 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
2285 break;
2286 case LY_STMT_NOTIFICATION:
2287 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
2288 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
2289 break;
2290 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002291 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002292 break;
2293 default:
2294 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "list");
2295 return LY_EVALID;
2296 }
2297 }
2298
2299 return LY_SUCCESS;
2300}
2301
Radek Krejci335332a2019-09-05 13:03:35 +02002302LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002303lysp_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 +02002304{
Radek Krejciad5963b2019-09-06 16:03:05 +02002305 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002306 uint16_t flags;
2307 struct lys_parser_ctx pctx = {0};
Radek Krejci335332a2019-09-05 13:03:35 +02002308
Michal Vaskob36053d2020-03-26 15:49:30 +01002309 pctx.format = LYS_IN_YANG;
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002310 pctx.parsed_mod = ctx->pmod;
Radek Krejci2efc45b2020-12-22 16:25:44 +01002311
Radek Krejciddace2c2021-01-08 11:30:56 +01002312 LOG_LOCSET(NULL, NULL, ctx->path, NULL);
Radek Krejci335332a2019-09-05 13:03:35 +02002313
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002314 switch (stmt->kw) {
2315 case LY_STMT_ACTION:
2316 case LY_STMT_RPC:
2317 ret = lysp_stmt_action(&pctx, stmt, NULL, (struct lysp_node_action **)result);
2318 break;
2319 case LY_STMT_ANYDATA:
2320 case LY_STMT_ANYXML:
2321 ret = lysp_stmt_any(&pctx, stmt, NULL, (struct lysp_node **)result);
2322 break;
2323 case LY_STMT_AUGMENT:
2324 ret = lysp_stmt_augment(&pctx, stmt, NULL, (struct lysp_node_augment **)result);
2325 break;
2326 case LY_STMT_BASE:
2327 ret = lysp_stmt_text_fields(&pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
2328 break;
2329 case LY_STMT_BIT:
2330 case LY_STMT_ENUM:
2331 ret = lysp_stmt_type_enum(&pctx, stmt, (struct lysp_type_enum **)result);
2332 break;
2333 case LY_STMT_CASE:
2334 ret = lysp_stmt_case(&pctx, stmt, NULL, (struct lysp_node **)result);
2335 break;
2336 case LY_STMT_CHOICE:
2337 ret = lysp_stmt_choice(&pctx, stmt, NULL, (struct lysp_node **)result);
2338 break;
2339 case LY_STMT_CONFIG:
2340 ret = lysp_stmt_config(&pctx, stmt, *(uint16_t **)result, exts);
2341 break;
2342 case LY_STMT_CONTACT:
2343 case LY_STMT_DESCRIPTION:
2344 case LY_STMT_ERROR_APP_TAG:
2345 case LY_STMT_ERROR_MESSAGE:
2346 case LY_STMT_KEY:
2347 case LY_STMT_NAMESPACE:
2348 case LY_STMT_ORGANIZATION:
2349 case LY_STMT_PRESENCE:
2350 case LY_STMT_REFERENCE:
2351 case LY_STMT_UNITS:
2352 ret = lysp_stmt_text_field(&pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
2353 break;
2354 case LY_STMT_CONTAINER:
2355 ret = lysp_stmt_container(&pctx, stmt, NULL, (struct lysp_node **)result);
2356 break;
2357 case LY_STMT_DEFAULT:
2358 case LY_STMT_IF_FEATURE:
2359 case LY_STMT_UNIQUE:
2360 ret = lysp_stmt_qnames(&pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
2361 break;
2362 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002363 ret = lysp_stmt_ext(&pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002364 break;
2365 case LY_STMT_FRACTION_DIGITS:
2366 ret = lysp_stmt_type_fracdigits(&pctx, stmt, *(uint8_t **)result, exts);
2367 break;
2368 case LY_STMT_GROUPING:
2369 ret = lysp_stmt_grouping(&pctx, stmt, NULL, (struct lysp_node_grp **)result);
2370 break;
2371 case LY_STMT_INPUT:
2372 case LY_STMT_OUTPUT: {
2373 struct lysp_node_action_inout *inout;
2374
2375 *result = inout = calloc(1, sizeof *inout);
2376 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
2377 ret = lysp_stmt_inout(&pctx, stmt, NULL, inout);
2378 break;
2379 }
2380 case LY_STMT_LEAF:
2381 ret = lysp_stmt_leaf(&pctx, stmt, NULL, (struct lysp_node **)result);
2382 break;
2383 case LY_STMT_LEAF_LIST:
2384 ret = lysp_stmt_leaflist(&pctx, stmt, NULL, (struct lysp_node **)result);
2385 break;
2386 case LY_STMT_LENGTH:
2387 case LY_STMT_MUST:
2388 case LY_STMT_RANGE:
2389 ret = lysp_stmt_restrs(&pctx, stmt, (struct lysp_restr **)result);
2390 break;
2391 case LY_STMT_LIST:
2392 ret = lysp_stmt_list(&pctx, stmt, NULL, (struct lysp_node **)result);
2393 break;
2394 case LY_STMT_MANDATORY:
2395 ret = lysp_stmt_mandatory(&pctx, stmt, *(uint16_t **)result, exts);
2396 break;
2397 case LY_STMT_MAX_ELEMENTS:
2398 flags = 0;
2399 ret = lysp_stmt_maxelements(&pctx, stmt, *(uint32_t **)result, &flags, exts);
2400 break;
2401 case LY_STMT_MIN_ELEMENTS:
2402 flags = 0;
2403 ret = lysp_stmt_minelements(&pctx, stmt, *(uint32_t **)result, &flags, exts);
2404 break;
2405 case LY_STMT_MODIFIER:
2406 ret = lysp_stmt_type_pattern_modifier(&pctx, stmt, (const char **)result, exts);
2407 break;
2408 case LY_STMT_NOTIFICATION:
2409 ret = lysp_stmt_notif(&pctx, stmt, NULL, (struct lysp_node_notif **)result);
2410 break;
2411 case LY_STMT_ORDERED_BY:
2412 ret = lysp_stmt_orderedby(&pctx, stmt, *(uint16_t **)result, exts);
2413 break;
2414 case LY_STMT_PATH: {
2415 const char *str_path = NULL;
2416
2417 LY_CHECK_RET(lysp_stmt_text_field(&pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
2418 ret = ly_path_parse(ctx->ctx, NULL, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
2419 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
2420 lydict_remove(ctx->ctx, str_path);
2421 break;
2422 }
2423 case LY_STMT_PATTERN:
2424 ret = lysp_stmt_type_pattern(&pctx, stmt, (struct lysp_restr **)result);
2425 break;
2426 case LY_STMT_POSITION:
2427 case LY_STMT_VALUE:
2428 flags = 0;
2429 ret = lysp_stmt_type_enum_value_pos(&pctx, stmt, *(int64_t **)result, &flags, exts);
2430 break;
2431 case LY_STMT_PREFIX:
2432 ret = lysp_stmt_text_field(&pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
2433 break;
2434 case LY_STMT_REFINE:
2435 ret = lysp_stmt_refine(&pctx, stmt, (struct lysp_refine **)result);
2436 break;
2437 case LY_STMT_REQUIRE_INSTANCE:
2438 flags = 0;
2439 ret = lysp_stmt_type_reqinstance(&pctx, stmt, *(uint8_t **)result, &flags, exts);
2440 break;
Michal Vasko69730152020-10-09 16:30:07 +02002441 case LY_STMT_STATUS:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002442 ret = lysp_stmt_status(&pctx, stmt, *(uint16_t **)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02002443 break;
Radek Krejci335332a2019-09-05 13:03:35 +02002444 case LY_STMT_TYPE: {
2445 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02002446
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002447 *result = type = calloc(1, sizeof *type);
2448 LY_CHECK_ERR_RET(!type, LOGMEM(ctx->ctx), LY_EMEM);
2449 ret = lysp_stmt_type(&pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02002450 break;
Radek Krejci0f969882020-08-21 16:56:47 +02002451 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002452 case LY_STMT_TYPEDEF:
2453 ret = lysp_stmt_typedef(&pctx, stmt, NULL, (struct lysp_tpdf **)result);
2454 break;
2455 case LY_STMT_USES:
2456 ret = lysp_stmt_uses(&pctx, stmt, NULL, (struct lysp_node **)result);
2457 break;
2458 case LY_STMT_WHEN:
2459 ret = lysp_stmt_when(&pctx, stmt, (struct lysp_when **)result);
2460 break;
Radek Krejci335332a2019-09-05 13:03:35 +02002461 default:
2462 LOGINT(ctx->ctx);
2463 return LY_EINT;
2464 }
2465
Radek Krejciddace2c2021-01-08 11:30:56 +01002466 LOG_LOCBACK(0, 0, 1, 0);
Radek Krejciad5963b2019-09-06 16:03:05 +02002467 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02002468}