blob: 3660b9624610596b726aabd156b9351715e4e9c6 [file] [log] [blame]
Radek Krejci335332a2019-09-05 13:03:35 +02001/**
Michal Vasko59892dd2022-05-13 11:02:30 +02002 * @file parser_common.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief libyang common parser functions.
Radek Krejci335332a2019-09-05 13:03:35 +02005 *
Michal Vasko59892dd2022-05-13 11:02:30 +02006 * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
Radek Krejci335332a2019-09-05 13:03:35 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Michal Vasko59892dd2022-05-13 11:02:30 +020015#define _GNU_SOURCE
16#define _POSIX_C_SOURCE 200809L /* strdup, strndup */
17
18#ifdef __APPLE__
19#define _DARWIN_C_SOURCE /* F_GETPATH */
20#endif
21
22#if defined (__NetBSD__) || defined (__OpenBSD__)
23/* realpath */
24#define _XOPEN_SOURCE 1
25#define _XOPEN_SOURCE_EXTENDED 1
26#endif
27
28#include "parser_internal.h"
29
Radek Krejci335332a2019-09-05 13:03:35 +020030#include <assert.h>
31#include <ctype.h>
32#include <errno.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020033#include <fcntl.h>
34#include <limits.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020035#include <stdint.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020036#include <stdio.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020037#include <stdlib.h>
38#include <string.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020039#include <unistd.h>
Radek Krejci335332a2019-09-05 13:03:35 +020040
Radek Krejci535ea9f2020-05-29 16:01:05 +020041#include "common.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020042#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020043#include "dict.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020044#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010045#include "log.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020046#include "parser_data.h"
Michal Vasko69730152020-10-09 16:30:07 +020047#include "path.h"
Radek Krejci77114102021-03-10 15:21:57 +010048#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020049#include "tree.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020050#include "tree_data.h"
51#include "tree_data_internal.h"
Radek Krejci335332a2019-09-05 13:03:35 +020052#include "tree_schema.h"
53#include "tree_schema_internal.h"
54
Michal Vasko59892dd2022-05-13 11:02:30 +020055void
56lyd_ctx_free(struct lyd_ctx *lydctx)
57{
58 ly_set_erase(&lydctx->node_types, NULL);
59 ly_set_erase(&lydctx->meta_types, NULL);
60 ly_set_erase(&lydctx->node_when, NULL);
61 ly_set_erase(&lydctx->ext_val, free);
62}
63
64LY_ERR
65lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op)
66{
67 const struct lyd_node *iter;
68
69 *op = NULL;
70
71 if (!parent) {
72 /* no parent, nothing to look for */
73 return LY_SUCCESS;
74 }
75
76 /* we need to find the operation node if it already exists */
77 for (iter = parent; iter; iter = lyd_parent(iter)) {
78 if (iter->schema && (iter->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
79 break;
80 }
81 }
82
83 if (!iter) {
84 /* no operation found */
85 return LY_SUCCESS;
86 }
87
88 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
89 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
90 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
91 return LY_EINVAL;
92 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
93 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
94 iter->schema->name);
95 return LY_EINVAL;
96 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
97 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
98 iter->schema->name);
99 return LY_EINVAL;
100 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
101 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
102 iter->schema->name);
103 return LY_EINVAL;
104 }
105
106 *op = (struct lyd_node *)iter;
107 return LY_SUCCESS;
108}
109
110LY_ERR
111lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
112{
113 LY_ERR rc = LY_SUCCESS;
114
115 LOG_LOCSET(snode, NULL, NULL, NULL);
116
117 if (lydctx->int_opts & LYD_INTOPT_ANY) {
118 /* nothing to check, everything is allowed */
119 goto cleanup;
120 }
121
122 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
123 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
124 rc = LY_EVALID;
125 goto cleanup;
126 }
127
128 if (snode->nodetype == LYS_RPC) {
129 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
130 if (lydctx->op_node) {
131 goto error_node_dup;
132 }
133 } else {
134 goto error_node_inval;
135 }
136 } else if (snode->nodetype == LYS_ACTION) {
137 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
138 if (lydctx->op_node) {
139 goto error_node_dup;
140 }
141 } else {
142 goto error_node_inval;
143 }
144 } else if (snode->nodetype == LYS_NOTIF) {
145 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
146 if (lydctx->op_node) {
147 goto error_node_dup;
148 }
149 } else {
150 goto error_node_inval;
151 }
152 }
153
154 /* success */
155 goto cleanup;
156
157error_node_dup:
158 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
159 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
160 lydctx->op_node->schema->name);
161 rc = LY_EVALID;
162 goto cleanup;
163
164error_node_inval:
165 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
166 snode->name);
167 rc = LY_EVALID;
168
169cleanup:
170 LOG_LOCBACK(1, 0, 0, 0);
171 return rc;
172}
173
174LY_ERR
175lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
176 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
177{
178 ly_bool incomplete;
179
180 LY_CHECK_RET(lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node));
181
182 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
183 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
184 }
185 return LY_SUCCESS;
186}
187
188LY_ERR
189lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
190 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
191 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
192{
193 ly_bool incomplete;
194 struct lyd_meta *first = NULL;
195
196 if (meta && *meta) {
197 /* remember the first metadata */
198 first = *meta;
199 }
200
201 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
202 hints, ctx_node, 0, &incomplete));
203
204 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
205 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
206 }
207
208 if (first) {
209 /* always return the first metadata */
210 *meta = first;
211 }
212
213 return LY_SUCCESS;
214}
215
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200216LY_ERR
217lyd_parse_check_keys(struct lyd_node *node)
218{
219 const struct lysc_node *skey = NULL;
220 const struct lyd_node *key;
221
222 assert(node->schema->nodetype == LYS_LIST);
223
224 key = lyd_child(node);
225 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
226 if (!key || (key->schema != skey)) {
227 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
228 return LY_EVALID;
229 }
230
231 key = key->next;
232 }
233
234 return LY_SUCCESS;
235}
236
237LY_ERR
238lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
239 struct lysc_ext_instance *ext)
240{
241 struct lyd_meta *meta2, *prev_meta = NULL;
242 struct lyd_ctx_ext_val *ext_val;
243
244 if (lysc_has_when(node->schema)) {
245 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
246 /* remember we need to evaluate this node's when */
247 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
248 }
249 }
250
251 LY_LIST_FOR(*meta, meta2) {
252 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
253 meta2->value.boolean) {
254 /* node is default according to the metadata */
255 node->flags |= LYD_DEFAULT;
256
257 /* delete the metadata */
258 if (prev_meta) {
259 prev_meta->next = meta2->next;
260 } else {
261 *meta = (*meta)->next;
262 }
263 lyd_free_meta_single(meta2);
264 break;
265 }
266
267 prev_meta = meta2;
268 }
269
270 if (ext) {
271 /* parsed for an extension */
272 node->flags |= LYD_EXT;
273
274 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
275 /* rememeber for validation */
276 ext_val = malloc(sizeof *ext_val);
277 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
278 ext_val->ext = ext;
279 ext_val->sibling = node;
280 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
281 }
282 }
283
284 return LY_SUCCESS;
285}
286
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100287static LY_ERR lysp_stmt_container(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
288 struct lysp_node **siblings);
289static LY_ERR lysp_stmt_choice(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
290 struct lysp_node **siblings);
291static LY_ERR lysp_stmt_case(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
292 struct lysp_node **siblings);
293static LY_ERR lysp_stmt_uses(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
294 struct lysp_node **siblings);
295static LY_ERR lysp_stmt_grouping(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
296 struct lysp_node_grp **groupings);
297static LY_ERR lysp_stmt_list(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
298 struct lysp_node **siblings);
299
Radek Krejci335332a2019-09-05 13:03:35 +0200300static LY_ERR
301lysp_stmt_validate_value(struct lys_parser_ctx *ctx, enum yang_arg val_type, const char *val)
302{
Radek Krejci857189e2020-09-01 13:26:36 +0200303 uint8_t prefix = 0;
304 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200305 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200306 size_t utf8_char_len;
307
308 while (*val) {
309 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200310 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200311
312 switch (val_type) {
313 case Y_IDENTIF_ARG:
314 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
315 break;
316 case Y_PREF_IDENTIF_ARG:
317 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
318 break;
319 case Y_STR_ARG:
320 case Y_MAYBE_STR_ARG:
321 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
322 break;
323 }
324 first = 0;
325 }
326
327 return LY_SUCCESS;
328}
329
330/**
331 * @brief Parse extension instance.
332 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100333 * @param[in] ctx parser context.
334 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100335 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200336 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
337 * @param[in,out] exts Extension instances to add to.
338 *
339 * @return LY_ERR values.
340 */
341static LY_ERR
Radek Krejcifc596f92021-02-26 22:40:26 +0100342lysp_stmt_ext(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200343 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200344{
345 struct lysp_ext_instance *e;
346
Michal Vaskob36053d2020-03-26 15:49:30 +0100347 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200348
349 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200350 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100351 e->parent_stmt = insubstmt;
352 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200353 e->parsed = NULL;
Radek Krejci335332a2019-09-05 13:03:35 +0200354 /* TODO (duplicate) e->child = stmt->child; */
355
356 /* get optional argument */
357 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200358 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200359 }
360
361 return LY_SUCCESS;
362}
363
364/**
365 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
366 * description, etc...
367 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100368 * @param[in] ctx parser context.
369 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200370 * @param[in] substmt_index Index of this substatement.
371 * @param[in,out] value Place to store the parsed value.
372 * @param[in] arg Type of the YANG keyword argument (of the value).
373 * @param[in,out] exts Extension instances to add to.
374 *
375 * @return LY_ERR values.
376 */
377static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100378lysp_stmt_text_field(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index,
Radek Krejci0f969882020-08-21 16:56:47 +0200379 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200380{
Radek Krejci335332a2019-09-05 13:03:35 +0200381 if (*value) {
Radek Krejci3972b332021-03-02 16:34:31 +0100382 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200383 return LY_EVALID;
384 }
385
386 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200387 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200388
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100389 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
390 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200391 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100392 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200393 break;
394 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100395 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200396 return LY_EVALID;
397 }
398 }
399 return LY_SUCCESS;
400}
401
402/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200403 * @brief Parse a qname that can have more instances such as if-feature.
404 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100405 * @param[in] ctx parser context.
406 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200407 * @param[in,out] qnames Parsed qnames to add to.
408 * @param[in] arg Type of the expected argument.
409 * @param[in,out] exts Extension instances to add to.
410 *
411 * @return LY_ERR values.
412 */
413static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100414lysp_stmt_qnames(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
Michal Vasko7f45cf22020-10-01 12:49:44 +0200415 struct lysp_qname **qnames, enum yang_arg arg, struct lysp_ext_instance **exts)
416{
417 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200418
419 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
420
421 /* allocate new pointer */
422 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
423 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100424 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200425
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100426 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
427 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200428 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100429 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200430 break;
431 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100432 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200433 return LY_EVALID;
434 }
435 }
436 return LY_SUCCESS;
437}
438
439/**
Radek Krejci335332a2019-09-05 13:03:35 +0200440 * @brief Parse a generic text field that can have more instances such as base.
441 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100442 * @param[in] ctx parser context.
443 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200444 * @param[in,out] texts Parsed values to add to.
445 * @param[in] arg Type of the expected argument.
446 * @param[in,out] exts Extension instances to add to.
447 *
448 * @return LY_ERR values.
449 */
450static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100451lysp_stmt_text_fields(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200452 const char ***texts, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200453{
454 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200455
456 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
457
458 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100459 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200460 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200461
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100462 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
463 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200464 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100465 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200466 break;
467 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100468 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200469 return LY_EVALID;
470 }
471 }
472 return LY_SUCCESS;
473}
474
475/**
476 * @brief Parse the status statement.
477 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100478 * @param[in] ctx parser context.
479 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200480 * @param[in,out] flags Flags to add to.
481 * @param[in,out] exts Extension instances to add to.
482 *
483 * @return LY_ERR values.
484 */
485static LY_ERR
486lysp_stmt_status(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
487{
488 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200489
490 if (*flags & LYS_STATUS_MASK) {
491 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
492 return LY_EVALID;
493 }
494
495 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
496 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100497 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200498 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100499 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200500 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100501 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200502 *flags |= LYS_STATUS_OBSLT;
503 } else {
504 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
505 return LY_EVALID;
506 }
507
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100508 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
509 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200510 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100511 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200512 break;
513 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100514 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200515 return LY_EVALID;
516 }
517 }
518 return LY_SUCCESS;
519}
520
521/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100522 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200523 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100524 * @param[in] ctx parser context.
525 * @param[in] stmt Source statement data from the parsed extension instance.
526 * @param[in,out] when_p When pointer to parse to.
527 *
528 * @return LY_ERR values.
529 */
530static LY_ERR
531lysp_stmt_when(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
532{
533 LY_ERR ret = LY_SUCCESS;
534 struct lysp_when *when;
535
536 if (*when_p) {
537 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
538 return LY_EVALID;
539 }
540
541 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
542
543 when = calloc(1, sizeof *when);
544 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
545 *when_p = when;
546
547 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
548
549 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
550 switch (child->kw) {
551 case LY_STMT_DESCRIPTION:
552 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
553 break;
554 case LY_STMT_REFERENCE:
555 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
556 break;
557 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100558 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100559 break;
560 default:
561 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "when");
562 return LY_EVALID;
563 }
564 }
565 return ret;
566}
567
568/**
569 * @brief Parse the config statement.
570 *
571 * @param[in] ctx parser context.
572 * @param[in] stmt Source statement data from the parsed extension instance.
573 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200574 * @param[in,out] exts Extension instances to add to.
575 *
576 * @return LY_ERR values.
577 */
578static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100579lysp_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 +0200580{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100581 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200582
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100583 if (*flags & LYS_CONFIG_MASK) {
584 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
585 return LY_EVALID;
586 }
587
588 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
589 arg_len = strlen(stmt->arg);
590 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
591 *flags |= LYS_CONFIG_W;
592 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
593 *flags |= LYS_CONFIG_R;
594 } else {
595 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
596 return LY_EVALID;
597 }
598
599 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
600 switch (child->kw) {
601 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100602 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100603 break;
604 default:
605 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "config");
606 return LY_EVALID;
607 }
608 }
609
610 return LY_SUCCESS;
611}
612
613/**
614 * @brief Parse the mandatory statement.
615 *
616 * @param[in] ctx parser context.
617 * @param[in] stmt Source statement data from the parsed extension instance.
618 * @param[in,out] flags Flags to add to.
619 * @param[in,out] exts Extension instances to add to.
620 *
621 * @return LY_ERR values.
622 */
623static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +0200624lysp_stmt_mandatory(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
625 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100626{
627 size_t arg_len;
628
629 if (*flags & LYS_MAND_MASK) {
630 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
631 return LY_EVALID;
632 }
633
634 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
635 arg_len = strlen(stmt->arg);
636 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
637 *flags |= LYS_MAND_TRUE;
638 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
639 *flags |= LYS_MAND_FALSE;
640 } else {
641 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
642 return LY_EVALID;
643 }
644
645 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
646 switch (child->kw) {
647 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100648 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100649 break;
650 default:
651 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "mandatory");
652 return LY_EVALID;
653 }
654 }
655
656 return LY_SUCCESS;
657}
658
659/**
660 * @brief Parse a restriction such as range or length.
661 *
662 * @param[in] ctx parser context.
663 * @param[in] stmt Source statement data from the parsed extension instance.
664 * @param[in,out] exts Extension instances to add to.
665 *
666 * @return LY_ERR values.
667 */
668static LY_ERR
669lysp_stmt_restr(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
670{
Radek Krejci335332a2019-09-05 13:03:35 +0200671 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200672 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100673 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200674
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100675 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
676 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200677 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100678 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200679 break;
680 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100681 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200682 break;
683 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100684 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200685 break;
686 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100687 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200688 break;
689 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100690 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200691 break;
692 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100693 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200694 return LY_EVALID;
695 }
696 }
697 return LY_SUCCESS;
698}
699
700/**
701 * @brief Parse a restriction that can have more instances such as must.
702 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100703 * @param[in] ctx parser context.
704 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200705 * @param[in,out] restrs Restrictions to add to.
706 *
707 * @return LY_ERR values.
708 */
709static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100710lysp_stmt_restrs(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200711{
712 struct lysp_restr *restr;
713
Michal Vaskob36053d2020-03-26 15:49:30 +0100714 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100715 return lysp_stmt_restr(ctx, stmt, restr);
716}
717
718/**
719 * @brief Parse the anydata or anyxml statement.
720 *
721 * @param[in] ctx parser context.
722 * @param[in] stmt Source statement data from the parsed extension instance.
723 * @param[in,out] siblings Siblings to add to.
724 *
725 * @return LY_ERR values.
726 */
727static LY_ERR
728lysp_stmt_any(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
729{
730 struct lysp_node_anydata *any;
731
732 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
733
734 /* create new structure and insert into siblings */
735 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
736
737 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
738 any->parent = parent;
739
740 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
741
742 /* parse substatements */
743 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
744 switch (child->kw) {
745 case LY_STMT_CONFIG:
746 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
747 break;
748 case LY_STMT_DESCRIPTION:
749 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
750 break;
751 case LY_STMT_IF_FEATURE:
752 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
753 break;
754 case LY_STMT_MANDATORY:
755 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
756 break;
757 case LY_STMT_MUST:
758 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
759 break;
760 case LY_STMT_REFERENCE:
761 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
762 break;
763 case LY_STMT_STATUS:
764 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
765 break;
766 case LY_STMT_WHEN:
767 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
768 break;
769 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100770 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100771 break;
772 default:
773 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
774 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(LY_STMT_ANYDATA) : ly_stmt2str(LY_STMT_ANYXML));
775 return LY_EVALID;
776 }
777 }
778
779 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200780}
781
782/**
783 * @brief Parse the value or position statement. Substatement of type enum statement.
784 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100785 * @param[in] ctx parser context.
786 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200787 * @param[in,out] value Value to write to.
788 * @param[in,out] flags Flags to write to.
789 * @param[in,out] exts Extension instances to add to.
790 *
791 * @return LY_ERR values.
792 */
793static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100794lysp_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 +0200795 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200796{
797 size_t arg_len;
798 char *ptr = NULL;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200799 long long int num = 0;
800 unsigned long long int unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200801
802 if (*flags & LYS_SET_VALUE) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100803 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200804 return LY_EVALID;
805 }
806 *flags |= LYS_SET_VALUE;
807
808 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
809
810 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100811 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
812 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
813 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200814 goto error;
815 }
816
817 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100818 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200819 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200820 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100821 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200822 goto error;
823 }
824 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200825 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200826 if (unum > UINT64_C(4294967295)) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100827 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200828 goto error;
829 }
830 }
831 /* we have not parsed the whole argument */
832 if ((size_t)(ptr - stmt->arg) != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100833 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200834 goto error;
835 }
836 if (errno == ERANGE) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100837 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200838 goto error;
839 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100840 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200841 *value = num;
842 } else {
843 *value = unum;
844 }
845
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100846 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
847 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200848 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100849 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 +0200850 break;
851 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100852 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200853 return LY_EVALID;
854 }
855 }
856 return LY_SUCCESS;
857
858error:
859 return LY_EVALID;
860}
861
862/**
863 * @brief Parse the enum or bit statement. Substatement of type statement.
864 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100865 * @param[in] ctx parser context.
866 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200867 * @param[in,out] enums Enums or bits to add to.
868 *
869 * @return LY_ERR values.
870 */
871static LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100872lysp_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 +0200873{
874 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200875
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100876 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 +0200877
Michal Vaskob36053d2020-03-26 15:49:30 +0100878 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200879
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100880 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +0200881 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
882 } /* else nothing specific for YANG_BIT */
883
Radek Krejci011e4aa2020-09-04 15:22:31 +0200884 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100885 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +0200886
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100887 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
888 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200889 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100890 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200891 break;
892 case LY_STMT_IF_FEATURE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100893 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(stmt->kw));
894 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200895 break;
896 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100897 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200898 break;
899 case LY_STMT_STATUS:
900 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
901 break;
902 case LY_STMT_VALUE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100903 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
904 ly_stmt2str(stmt->kw)), LY_EVALID);
905 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200906 break;
907 case LY_STMT_POSITION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100908 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
909 ly_stmt2str(stmt->kw)), LY_EVALID);
910 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200911 break;
912 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100913 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200914 break;
915 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100916 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200917 return LY_EVALID;
918 }
919 }
920 return LY_SUCCESS;
921}
922
923/**
924 * @brief Parse the fraction-digits statement. Substatement of type statement.
925 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100926 * @param[in] ctx parser context.
927 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200928 * @param[in,out] fracdig Value to write to.
929 * @param[in,out] exts Extension instances to add to.
930 *
931 * @return LY_ERR values.
932 */
933static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +0200934lysp_stmt_type_fracdigits(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
935 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200936{
937 char *ptr;
938 size_t arg_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200939 unsigned long long int num;
Radek Krejci335332a2019-09-05 13:03:35 +0200940
941 if (*fracdig) {
942 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
943 return LY_EVALID;
944 }
945
946 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
947 arg_len = strlen(stmt->arg);
948 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
949 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
950 return LY_EVALID;
951 }
952
953 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200954 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200955 /* we have not parsed the whole argument */
956 if ((size_t)(ptr - stmt->arg) != arg_len) {
957 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
958 return LY_EVALID;
959 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100960 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200961 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
962 return LY_EVALID;
963 }
964 *fracdig = num;
965
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100966 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
967 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200968 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100969 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200970 break;
971 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100972 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +0200973 return LY_EVALID;
974 }
975 }
976 return LY_SUCCESS;
977}
978
979/**
980 * @brief Parse the require-instance statement. Substatement of type statement.
981 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100982 * @param[in] ctx parser context.
983 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200984 * @param[in,out] reqinst Value to write to.
985 * @param[in,out] flags Flags to write to.
986 * @param[in,out] exts Extension instances to add to.
987 *
988 * @return LY_ERR values.
989 */
990static LY_ERR
991lysp_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 +0200992 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200993{
994 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200995
996 if (*flags & LYS_SET_REQINST) {
997 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
998 return LY_EVALID;
999 }
1000 *flags |= LYS_SET_REQINST;
1001
1002 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1003 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001004 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001005 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001006 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001007 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1008 return LY_EVALID;
1009 }
1010
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001011 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1012 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001013 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001014 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001015 break;
1016 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001017 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001018 return LY_EVALID;
1019 }
1020 }
1021 return LY_SUCCESS;
1022}
1023
1024/**
1025 * @brief Parse the modifier statement. Substatement of type pattern statement.
1026 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001027 * @param[in] ctx parser context.
1028 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001029 * @param[in,out] pat Value to write to.
1030 * @param[in,out] exts Extension instances to add to.
1031 *
1032 * @return LY_ERR values.
1033 */
1034static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02001035lysp_stmt_type_pattern_modifier(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
1036 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001037{
1038 size_t arg_len;
1039 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001040
Radek Krejcif13b87b2020-12-01 22:02:17 +01001041 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001042 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1043 return LY_EVALID;
1044 }
1045
1046 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1047 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001048 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001049 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1050 return LY_EVALID;
1051 }
1052
1053 /* replace the value in the dictionary */
1054 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001055 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001056 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001057 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001058
Radek Krejcif13b87b2020-12-01 22:02:17 +01001059 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1060 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001061 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001062
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001063 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1064 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001065 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001066 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001067 break;
1068 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001069 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001070 return LY_EVALID;
1071 }
1072 }
1073 return LY_SUCCESS;
1074}
1075
1076/**
1077 * @brief Parse the pattern statement. Substatement of type statement.
1078 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001079 * @param[in] ctx parser context.
1080 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001081 * @param[in,out] patterns Restrictions to add to.
1082 *
1083 * @return LY_ERR values.
1084 */
1085static LY_ERR
1086lysp_stmt_type_pattern(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
1087{
1088 char *buf;
1089 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001090 struct lysp_restr *restr;
1091
1092 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001093 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001094 arg_len = strlen(stmt->arg);
1095
1096 /* add special meaning first byte */
1097 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001098 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001099 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001100 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001101 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001102 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001103 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001104
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001105 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1106 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001107 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001108 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001109 break;
1110 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001111 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001112 break;
1113 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001114 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001115 break;
1116 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001117 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001118 break;
1119 case LY_STMT_MODIFIER:
1120 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001121 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001122 break;
1123 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001124 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001125 break;
1126 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001127 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001128 return LY_EVALID;
1129 }
1130 }
1131 return LY_SUCCESS;
1132}
1133
1134/**
1135 * @brief Parse the type statement.
1136 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001137 * @param[in] ctx parser context.
1138 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001139 * @param[in,out] type Type to wrote to.
1140 *
1141 * @return LY_ERR values.
1142 */
1143static LY_ERR
1144lysp_stmt_type(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
1145{
1146 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001147 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001148 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001149
1150 if (type->name) {
1151 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1152 return LY_EVALID;
1153 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001154
1155 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001156 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001157 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001158
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001159 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1160 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001161 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001162 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001163 type->flags |= LYS_SET_BASE;
1164 break;
1165 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001166 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001167 type->flags |= LYS_SET_BIT;
1168 break;
1169 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001170 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001171 type->flags |= LYS_SET_ENUM;
1172 break;
1173 case LY_STMT_FRACTION_DIGITS:
1174 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1175 type->flags |= LYS_SET_FRDIGITS;
1176 break;
1177 case LY_STMT_LENGTH:
1178 if (type->length) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001179 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001180 return LY_EVALID;
1181 }
1182 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001183 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001184
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001185 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001186 type->flags |= LYS_SET_LENGTH;
1187 break;
1188 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001189 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001190 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001191 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001192 lydict_remove(PARSER_CTX(ctx), str_path);
1193 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001194 type->flags |= LYS_SET_PATH;
1195 break;
1196 case LY_STMT_PATTERN:
1197 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1198 type->flags |= LYS_SET_PATTERN;
1199 break;
1200 case LY_STMT_RANGE:
1201 if (type->range) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001202 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001203 return LY_EVALID;
1204 }
1205 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001206 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001207
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001208 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001209 type->flags |= LYS_SET_RANGE;
1210 break;
1211 case LY_STMT_REQUIRE_INSTANCE:
1212 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001213 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001214 break;
1215 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001216 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001217 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1218 type->flags |= LYS_SET_TYPE;
1219 break;
1220 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001221 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001222 break;
1223 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001224 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001225 return LY_EVALID;
1226 }
1227 }
1228 return LY_SUCCESS;
1229}
1230
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001231/**
1232 * @brief Parse the leaf statement.
1233 *
1234 * @param[in] ctx parser context.
1235 * @param[in] stmt Source statement data from the parsed extension instance.
1236 * @param[in] parent Parent node to connect to (not into).
1237 * @param[in,out] siblings Siblings to add to.
1238 *
1239 * @return LY_ERR values.
1240 */
1241static LY_ERR
1242lysp_stmt_leaf(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
1243{
1244 struct lysp_node_leaf *leaf;
1245
1246 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1247
1248 /* create new leaf structure */
1249 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1250 leaf->nodetype = LYS_LEAF;
1251 leaf->parent = parent;
1252
1253 /* get name */
1254 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1255
1256 /* parse substatements */
1257 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1258 switch (child->kw) {
1259 case LY_STMT_CONFIG:
1260 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1261 break;
1262 case LY_STMT_DEFAULT:
1263 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dflt.str, Y_STR_ARG, &leaf->exts));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001264 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001265 break;
1266 case LY_STMT_DESCRIPTION:
1267 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1268 break;
1269 case LY_STMT_IF_FEATURE:
1270 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1271 break;
1272 case LY_STMT_MANDATORY:
1273 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1274 break;
1275 case LY_STMT_MUST:
1276 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1277 break;
1278 case LY_STMT_REFERENCE:
1279 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1280 break;
1281 case LY_STMT_STATUS:
1282 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1283 break;
1284 case LY_STMT_TYPE:
1285 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1286 break;
1287 case LY_STMT_UNITS:
1288 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1289 break;
1290 case LY_STMT_WHEN:
1291 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1292 break;
1293 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001294 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001295 break;
1296 default:
1297 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "leaf");
1298 return LY_EVALID;
1299 }
1300 }
1301
1302 /* mandatory substatements */
1303 if (!leaf->type.name) {
1304 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1305 return LY_EVALID;
1306 }
1307
1308 return LY_SUCCESS;
1309}
1310
1311/**
1312 * @brief Parse the max-elements statement.
1313 *
1314 * @param[in] ctx parser context.
1315 * @param[in] stmt Source statement data from the parsed extension instance.
1316 * @param[in,out] max Value to write to.
1317 * @param[in,out] flags Flags to write to.
1318 * @param[in,out] exts Extension instances to add to.
1319 *
1320 * @return LY_ERR values.
1321 */
1322static LY_ERR
1323lysp_stmt_maxelements(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
1324 uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
1325{
1326 size_t arg_len;
1327 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001328 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001329
1330 if (*flags & LYS_SET_MAX) {
1331 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1332 return LY_EVALID;
1333 }
1334 *flags |= LYS_SET_MAX;
1335
1336 /* get value */
1337 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1338 arg_len = strlen(stmt->arg);
1339
1340 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1341 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1342 return LY_EVALID;
1343 }
1344
1345 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1346 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001347 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001348 /* we have not parsed the whole argument */
1349 if ((size_t)(ptr - stmt->arg) != arg_len) {
1350 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1351 return LY_EVALID;
1352 }
1353 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1354 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1355 return LY_EVALID;
1356 }
1357
1358 *max = num;
1359 } else {
1360 /* unbounded */
1361 *max = 0;
1362 }
1363
1364 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1365 switch (child->kw) {
1366 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001367 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001368 break;
1369 default:
1370 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "max-elements");
1371 return LY_EVALID;
1372 }
1373 }
1374
1375 return LY_SUCCESS;
1376}
1377
1378/**
1379 * @brief Parse the min-elements statement.
1380 *
1381 * @param[in] ctx parser context.
1382 * @param[in] stmt Source statement data from the parsed extension instance.
1383 * @param[in,out] min Value to write to.
1384 * @param[in,out] flags Flags to write to.
1385 * @param[in,out] exts Extension instances to add to.
1386 *
1387 * @return LY_ERR values.
1388 */
1389static LY_ERR
1390lysp_stmt_minelements(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt,
1391 uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
1392{
1393 size_t arg_len;
1394 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001395 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001396
1397 if (*flags & LYS_SET_MIN) {
1398 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
1399 return LY_EVALID;
1400 }
1401 *flags |= LYS_SET_MIN;
1402
1403 /* get value */
1404 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1405 arg_len = strlen(stmt->arg);
1406
1407 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
1408 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1409 return LY_EVALID;
1410 }
1411
1412 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001413 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001414 /* we have not parsed the whole argument */
1415 if ((size_t)(ptr - stmt->arg) != arg_len) {
1416 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1417 return LY_EVALID;
1418 }
1419 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1420 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
1421 return LY_EVALID;
1422 }
1423 *min = num;
1424
1425 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1426 switch (child->kw) {
1427 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001428 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001429 break;
1430 default:
1431 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "min-elements");
1432 return LY_EVALID;
1433 }
1434 }
1435
1436 return LY_SUCCESS;
1437}
1438
1439/**
1440 * @brief Parse the ordered-by statement.
1441 *
1442 * @param[in] ctx parser context.
1443 * @param[in] stmt Source statement data from the parsed extension instance.
1444 * @param[in,out] flags Flags to write to.
1445 * @param[in,out] exts Extension instances to add to.
1446 *
1447 * @return LY_ERR values.
1448 */
1449static LY_ERR
1450lysp_stmt_orderedby(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1451{
1452 size_t arg_len;
1453
1454 if (*flags & LYS_ORDBY_MASK) {
1455 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
1456 return LY_EVALID;
1457 }
1458
1459 /* get value */
1460 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1461 arg_len = strlen(stmt->arg);
1462 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
1463 *flags |= LYS_MAND_TRUE;
1464 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
1465 *flags |= LYS_MAND_FALSE;
1466 } else {
1467 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
1468 return LY_EVALID;
1469 }
1470
1471 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1472 switch (child->kw) {
1473 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001474 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001475 break;
1476 default:
1477 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "ordered-by");
1478 return LY_EVALID;
1479 }
1480 }
1481
1482 return LY_SUCCESS;
1483}
1484
1485/**
1486 * @brief Parse the leaf-list statement.
1487 *
1488 * @param[in] ctx parser context.
1489 * @param[in] stmt Source statement data from the parsed extension instance.
1490 * @param[in] parent Parent node to connect to (not into).
1491 * @param[in,out] siblings Siblings to add to.
1492 *
1493 * @return LY_ERR values.
1494 */
1495static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02001496lysp_stmt_leaflist(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
1497 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001498{
1499 struct lysp_node_leaflist *llist;
1500
1501 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1502
1503 /* create new leaf-list structure */
1504 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
1505 llist->nodetype = LYS_LEAFLIST;
1506 llist->parent = parent;
1507
1508 /* get name */
1509 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
1510
1511 /* parse substatements */
1512 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1513 switch (child->kw) {
1514 case LY_STMT_CONFIG:
1515 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
1516 break;
1517 case LY_STMT_DEFAULT:
1518 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
1519 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
1520 break;
1521 case LY_STMT_DESCRIPTION:
1522 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
1523 break;
1524 case LY_STMT_IF_FEATURE:
1525 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
1526 break;
1527 case LY_STMT_MAX_ELEMENTS:
1528 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
1529 break;
1530 case LY_STMT_MIN_ELEMENTS:
1531 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
1532 break;
1533 case LY_STMT_MUST:
1534 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
1535 break;
1536 case LY_STMT_ORDERED_BY:
1537 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
1538 break;
1539 case LY_STMT_REFERENCE:
1540 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
1541 break;
1542 case LY_STMT_STATUS:
1543 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
1544 break;
1545 case LY_STMT_TYPE:
1546 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
1547 break;
1548 case LY_STMT_UNITS:
1549 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
1550 break;
1551 case LY_STMT_WHEN:
1552 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
1553 break;
1554 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001555 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001556 break;
1557 default:
1558 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "llist");
1559 return LY_EVALID;
1560 }
1561 }
1562
1563 /* mandatory substatements */
1564 if (!llist->type.name) {
1565 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
1566 return LY_EVALID;
1567 }
1568
1569 return LY_SUCCESS;
1570}
1571
1572/**
1573 * @brief Parse the refine statement.
1574 *
1575 * @param[in] ctx parser context.
1576 * @param[in] stmt Source statement data from the parsed extension instance.
1577 * @param[in,out] refines Refines to add to.
1578 *
1579 * @return LY_ERR values.
1580 */
1581static LY_ERR
1582lysp_stmt_refine(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
1583{
1584 struct lysp_refine *rf;
1585
1586 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1587
1588 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
1589
1590 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
1591
1592 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1593 switch (child->kw) {
1594 case LY_STMT_CONFIG:
1595 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
1596 break;
1597 case LY_STMT_DEFAULT:
1598 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
1599 break;
1600 case LY_STMT_DESCRIPTION:
1601 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
1602 break;
1603 case LY_STMT_IF_FEATURE:
1604 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
1605 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
1606 break;
1607 case LY_STMT_MAX_ELEMENTS:
1608 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
1609 break;
1610 case LY_STMT_MIN_ELEMENTS:
1611 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
1612 break;
1613 case LY_STMT_MUST:
1614 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
1615 break;
1616 case LY_STMT_MANDATORY:
1617 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
1618 break;
1619 case LY_STMT_REFERENCE:
1620 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
1621 break;
1622 case LY_STMT_PRESENCE:
1623 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
1624 break;
1625 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001626 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001627 break;
1628 default:
1629 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "refine");
1630 return LY_EVALID;
1631 }
1632 }
1633
1634 return LY_SUCCESS;
1635}
1636
1637/**
1638 * @brief Parse the typedef statement.
1639 *
1640 * @param[in] ctx parser context.
1641 * @param[in] stmt Source statement data from the parsed extension instance.
1642 * @param[in] parent Parent node to connect to (not into).
1643 * @param[in,out] typedefs Typedefs to add to.
1644 *
1645 * @return LY_ERR values.
1646 */
1647static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02001648lysp_stmt_typedef(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
1649 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001650{
1651 struct lysp_tpdf *tpdf;
1652
1653 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1654
1655 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
1656
1657 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
1658
1659 /* parse substatements */
1660 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1661 switch (child->kw) {
1662 case LY_STMT_DEFAULT:
1663 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dflt.str, Y_STR_ARG, &tpdf->exts));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001664 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001665 break;
1666 case LY_STMT_DESCRIPTION:
1667 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
1668 break;
1669 case LY_STMT_REFERENCE:
1670 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
1671 break;
1672 case LY_STMT_STATUS:
1673 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
1674 break;
1675 case LY_STMT_TYPE:
1676 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
1677 break;
1678 case LY_STMT_UNITS:
1679 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
1680 break;
1681 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001682 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001683 break;
1684 default:
1685 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "typedef");
1686 return LY_EVALID;
1687 }
1688 }
1689
1690 /* mandatory substatements */
1691 if (!tpdf->type.name) {
1692 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
1693 return LY_EVALID;
1694 }
1695
1696 /* store data for collision check */
1697 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
1698 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
1699 }
1700
1701 return LY_SUCCESS;
1702}
1703
1704/**
1705 * @brief Parse the input or output statement.
1706 *
1707 * @param[in] ctx parser context.
1708 * @param[in] stmt Source statement data from the parsed extension instance.
1709 * @param[in] parent Parent node to connect to (not into).
1710 * @param[in,out] inout_p Input/output pointer to write to.
1711 *
1712 * @return LY_ERR values.
1713 */
1714static LY_ERR
1715lysp_stmt_inout(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
1716 struct lysp_node_action_inout *inout_p)
1717{
1718 if (inout_p->nodetype) {
1719 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
1720 return LY_EVALID;
1721 }
1722
1723 /* initiate structure */
1724 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
1725 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
1726 inout_p->parent = parent;
1727
1728 /* parse substatements */
1729 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1730 switch (child->kw) {
1731 case LY_STMT_ANYDATA:
1732 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(stmt->kw));
1733 /* fall through */
1734 case LY_STMT_ANYXML:
1735 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
1736 break;
1737 case LY_STMT_CHOICE:
1738 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
1739 break;
1740 case LY_STMT_CONTAINER:
1741 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
1742 break;
1743 case LY_STMT_LEAF:
1744 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
1745 break;
1746 case LY_STMT_LEAF_LIST:
1747 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
1748 break;
1749 case LY_STMT_LIST:
1750 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
1751 break;
1752 case LY_STMT_USES:
1753 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
1754 break;
1755 case LY_STMT_TYPEDEF:
1756 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
1757 break;
1758 case LY_STMT_MUST:
1759 PARSER_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(stmt->kw));
1760 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
1761 break;
1762 case LY_STMT_GROUPING:
1763 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
1764 break;
1765 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001766 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001767 break;
1768 default:
1769 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
1770 return LY_EVALID;
1771 }
1772 }
1773
1774 if (!inout_p->child) {
1775 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(stmt->kw));
1776 return LY_EVALID;
1777 }
1778
1779 return LY_SUCCESS;
1780}
1781
1782/**
1783 * @brief Parse the action statement.
1784 *
1785 * @param[in] ctx parser context.
1786 * @param[in] stmt Source statement data from the parsed extension instance.
1787 * @param[in] parent Parent node to connect to (not into).
1788 * @param[in,out] actions Actions to add to.
1789 *
1790 * @return LY_ERR values.
1791 */
1792static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02001793lysp_stmt_action(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
1794 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001795{
1796 struct lysp_node_action *act;
1797
1798 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1799
1800 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
1801
1802 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
1803 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
1804 act->parent = parent;
1805
1806 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1807 switch (child->kw) {
1808 case LY_STMT_DESCRIPTION:
1809 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
1810 break;
1811 case LY_STMT_IF_FEATURE:
1812 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
1813 break;
1814 case LY_STMT_REFERENCE:
1815 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
1816 break;
1817 case LY_STMT_STATUS:
1818 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
1819 break;
1820
1821 case LY_STMT_INPUT:
1822 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
1823 break;
1824 case LY_STMT_OUTPUT:
1825 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
1826 break;
1827
1828 case LY_STMT_TYPEDEF:
1829 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
1830 break;
1831 case LY_STMT_GROUPING:
1832 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
1833 break;
1834 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001835 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 +01001836 break;
1837 default:
1838 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), parent ? "action" : "rpc");
1839 return LY_EVALID;
1840 }
1841 }
1842
1843 /* always initialize inout, they are technically present (needed for later deviations/refines) */
1844 if (!act->input.nodetype) {
1845 act->input.nodetype = LYS_INPUT;
1846 act->input.parent = &act->node;
1847 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
1848 }
1849 if (!act->output.nodetype) {
1850 act->output.nodetype = LYS_OUTPUT;
1851 act->output.parent = &act->node;
1852 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
1853 }
1854
1855 return LY_SUCCESS;
1856}
1857
1858/**
1859 * @brief Parse the notification 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] notifs Notifications to add to.
1865 *
1866 * @return LY_ERR values.
1867 */
1868static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02001869lysp_stmt_notif(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
1870 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001871{
1872 struct lysp_node_notif *notif;
1873
1874 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1875
1876 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
1877
1878 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
1879 notif->nodetype = LYS_NOTIF;
1880 notif->parent = parent;
1881
1882 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1883 switch (child->kw) {
1884 case LY_STMT_DESCRIPTION:
1885 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
1886 break;
1887 case LY_STMT_IF_FEATURE:
1888 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
1889 break;
1890 case LY_STMT_REFERENCE:
1891 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
1892 break;
1893 case LY_STMT_STATUS:
1894 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
1895 break;
1896
1897 case LY_STMT_ANYDATA:
1898 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
1899 /* fall through */
1900 case LY_STMT_ANYXML:
1901 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
1902 break;
1903 case LY_STMT_CHOICE:
1904 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
1905 break;
1906 case LY_STMT_CONTAINER:
1907 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
1908 break;
1909 case LY_STMT_LEAF:
1910 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
1911 break;
1912 case LY_STMT_LEAF_LIST:
1913 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
1914 break;
1915 case LY_STMT_LIST:
1916 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
1917 break;
1918 case LY_STMT_USES:
1919 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
1920 break;
1921
1922 case LY_STMT_MUST:
1923 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
1924 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
1925 break;
1926 case LY_STMT_TYPEDEF:
1927 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
1928 break;
1929 case LY_STMT_GROUPING:
1930 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
1931 break;
1932 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001933 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001934 break;
1935 default:
1936 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "notification");
1937 return LY_EVALID;
1938 }
1939 }
1940
1941 return LY_SUCCESS;
1942}
1943
1944/**
1945 * @brief Parse the grouping statement.
1946 *
1947 * @param[in] ctx parser context.
1948 * @param[in] stmt Source statement data from the parsed extension instance.
1949 * @param[in] parent Parent node to connect to (not into).
1950 * @param[in,out] groupings Groupings to add to.
1951 *
1952 * @return LY_ERR values.
1953 */
1954static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02001955lysp_stmt_grouping(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
1956 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001957{
1958 struct lysp_node_grp *grp;
1959
1960 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1961
1962 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
1963
1964 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
1965 grp->nodetype = LYS_GROUPING;
1966 grp->parent = parent;
1967
1968 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1969 switch (child->kw) {
1970 case LY_STMT_DESCRIPTION:
1971 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
1972 break;
1973 case LY_STMT_REFERENCE:
1974 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
1975 break;
1976 case LY_STMT_STATUS:
1977 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
1978 break;
1979
1980 case LY_STMT_ANYDATA:
1981 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
1982 /* fall through */
1983 case LY_STMT_ANYXML:
1984 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
1985 break;
1986 case LY_STMT_CHOICE:
1987 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
1988 break;
1989 case LY_STMT_CONTAINER:
1990 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
1991 break;
1992 case LY_STMT_LEAF:
1993 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
1994 break;
1995 case LY_STMT_LEAF_LIST:
1996 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
1997 break;
1998 case LY_STMT_LIST:
1999 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2000 break;
2001 case LY_STMT_USES:
2002 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2003 break;
2004
2005 case LY_STMT_TYPEDEF:
2006 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2007 break;
2008 case LY_STMT_ACTION:
2009 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2010 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2011 break;
2012 case LY_STMT_GROUPING:
2013 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2014 break;
2015 case LY_STMT_NOTIFICATION:
2016 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2017 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2018 break;
2019 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002020 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002021 break;
2022 default:
2023 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "grouping");
2024 return LY_EVALID;
2025 }
2026 }
2027
2028 return LY_SUCCESS;
2029}
2030
2031/**
2032 * @brief Parse the augment statement.
2033 *
2034 * @param[in] ctx parser context.
2035 * @param[in] stmt Source statement data from the parsed extension instance.
2036 * @param[in] parent Parent node to connect to (not into).
2037 * @param[in,out] augments Augments to add to.
2038 *
2039 * @return LY_ERR values.
2040 */
2041static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02002042lysp_stmt_augment(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
2043 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002044{
2045 struct lysp_node_augment *aug;
2046
2047 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2048
2049 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2050
2051 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2052 aug->nodetype = LYS_AUGMENT;
2053 aug->parent = parent;
2054
2055 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2056 switch (child->kw) {
2057 case LY_STMT_DESCRIPTION:
2058 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2059 break;
2060 case LY_STMT_IF_FEATURE:
2061 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2062 break;
2063 case LY_STMT_REFERENCE:
2064 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2065 break;
2066 case LY_STMT_STATUS:
2067 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2068 break;
2069 case LY_STMT_WHEN:
2070 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2071 break;
2072
2073 case LY_STMT_ANYDATA:
2074 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2075 /* fall through */
2076 case LY_STMT_ANYXML:
2077 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2078 break;
2079 case LY_STMT_CASE:
2080 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2081 break;
2082 case LY_STMT_CHOICE:
2083 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2084 break;
2085 case LY_STMT_CONTAINER:
2086 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2087 break;
2088 case LY_STMT_LEAF:
2089 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2090 break;
2091 case LY_STMT_LEAF_LIST:
2092 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2093 break;
2094 case LY_STMT_LIST:
2095 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2096 break;
2097 case LY_STMT_USES:
2098 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2099 break;
2100
2101 case LY_STMT_ACTION:
2102 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2103 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2104 break;
2105 case LY_STMT_NOTIFICATION:
2106 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2107 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2108 break;
2109 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002110 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002111 break;
2112 default:
2113 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "augment");
2114 return LY_EVALID;
2115 }
2116 }
2117
2118 return LY_SUCCESS;
2119}
2120
2121/**
2122 * @brief Parse the uses statement.
2123 *
2124 * @param[in] ctx parser context.
2125 * @param[in] stmt Source statement data from the parsed extension instance.
2126 * @param[in] parent Parent node to connect to (not into).
2127 * @param[in,out] siblings Siblings to add to.
2128 *
2129 * @return LY_ERR values.
2130 */
2131static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02002132lysp_stmt_uses(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
2133 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002134{
2135 struct lysp_node_uses *uses;
2136
2137 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2138
2139 /* create uses structure */
2140 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2141
2142 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2143 uses->nodetype = LYS_USES;
2144 uses->parent = parent;
2145
2146 /* parse substatements */
2147 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2148 switch (child->kw) {
2149 case LY_STMT_DESCRIPTION:
2150 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2151 break;
2152 case LY_STMT_IF_FEATURE:
2153 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2154 break;
2155 case LY_STMT_REFERENCE:
2156 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2157 break;
2158 case LY_STMT_STATUS:
2159 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2160 break;
2161 case LY_STMT_WHEN:
2162 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2163 break;
2164
2165 case LY_STMT_REFINE:
2166 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2167 break;
2168 case LY_STMT_AUGMENT:
2169 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2170 break;
2171 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002172 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002173 break;
2174 default:
2175 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "uses");
2176 return LY_EVALID;
2177 }
2178 }
2179
2180 return LY_SUCCESS;
2181}
2182
2183/**
2184 * @brief Parse the case statement.
2185 *
2186 * @param[in] ctx parser context.
2187 * @param[in] stmt Source statement data from the parsed extension instance.
2188 * @param[in] parent Parent node to connect to (not into).
2189 * @param[in,out] siblings Siblings to add to.
2190 *
2191 * @return LY_ERR values.
2192 */
2193static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02002194lysp_stmt_case(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
2195 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002196{
2197 struct lysp_node_case *cas;
2198
2199 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2200
2201 /* create new case structure */
2202 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2203
2204 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2205 cas->nodetype = LYS_CASE;
2206 cas->parent = parent;
2207
2208 /* parse substatements */
2209 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2210 switch (child->kw) {
2211 case LY_STMT_DESCRIPTION:
2212 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2213 break;
2214 case LY_STMT_IF_FEATURE:
2215 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2216 break;
2217 case LY_STMT_REFERENCE:
2218 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2219 break;
2220 case LY_STMT_STATUS:
2221 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2222 break;
2223 case LY_STMT_WHEN:
2224 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2225 break;
2226
2227 case LY_STMT_ANYDATA:
2228 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2229 /* fall through */
2230 case LY_STMT_ANYXML:
2231 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2232 break;
2233 case LY_STMT_CHOICE:
2234 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2235 break;
2236 case LY_STMT_CONTAINER:
2237 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2238 break;
2239 case LY_STMT_LEAF:
2240 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2241 break;
2242 case LY_STMT_LEAF_LIST:
2243 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2244 break;
2245 case LY_STMT_LIST:
2246 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2247 break;
2248 case LY_STMT_USES:
2249 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2250 break;
2251 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002252 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002253 break;
2254 default:
2255 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "case");
2256 return LY_EVALID;
2257 }
2258 }
2259 return LY_SUCCESS;
2260}
2261
2262/**
2263 * @brief Parse the choice statement.
2264 *
2265 * @param[in] ctx parser context.
2266 * @param[in] stmt Source statement data from the parsed extension instance.
2267 * @param[in] parent Parent node to connect to (not into).
2268 * @param[in,out] siblings Siblings to add to.
2269 *
2270 * @return LY_ERR values.
2271 */
2272static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02002273lysp_stmt_choice(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
2274 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002275{
2276 struct lysp_node_choice *choice;
2277
2278 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2279
2280 /* create new choice structure */
2281 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2282
2283 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2284 choice->nodetype = LYS_CHOICE;
2285 choice->parent = parent;
2286
2287 /* parse substatements */
2288 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2289 switch (child->kw) {
2290 case LY_STMT_CONFIG:
2291 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2292 break;
2293 case LY_STMT_DESCRIPTION:
2294 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2295 break;
2296 case LY_STMT_IF_FEATURE:
2297 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2298 break;
2299 case LY_STMT_MANDATORY:
2300 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2301 break;
2302 case LY_STMT_REFERENCE:
2303 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2304 break;
2305 case LY_STMT_STATUS:
2306 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2307 break;
2308 case LY_STMT_WHEN:
2309 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2310 break;
2311 case LY_STMT_DEFAULT:
2312 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dflt.str, Y_PREF_IDENTIF_ARG, &choice->exts));
Michal Vasko8a67eff2021-12-07 14:04:47 +01002313 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002314 break;
2315 case LY_STMT_ANYDATA:
2316 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2317 /* fall through */
2318 case LY_STMT_ANYXML:
2319 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2320 break;
2321 case LY_STMT_CASE:
2322 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2323 break;
2324 case LY_STMT_CHOICE:
2325 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2326 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2327 break;
2328 case LY_STMT_CONTAINER:
2329 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2330 break;
2331 case LY_STMT_LEAF:
2332 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2333 break;
2334 case LY_STMT_LEAF_LIST:
2335 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2336 break;
2337 case LY_STMT_LIST:
2338 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2339 break;
2340 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002341 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002342 break;
2343 default:
2344 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "choice");
2345 return LY_EVALID;
2346 }
2347 }
2348 return LY_SUCCESS;
2349}
2350
2351/**
2352 * @brief Parse the container statement.
2353 *
2354 * @param[in] ctx parser context.
2355 * @param[in] stmt Source statement data from the parsed extension instance.
2356 * @param[in] parent Parent node to connect to (not into).
2357 * @param[in,out] siblings Siblings to add to.
2358 *
2359 * @return LY_ERR values.
2360 */
2361static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02002362lysp_stmt_container(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
2363 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002364{
2365 struct lysp_node_container *cont;
2366
2367 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2368
2369 /* create new container structure */
2370 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2371
2372 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2373 cont->nodetype = LYS_CONTAINER;
2374 cont->parent = parent;
2375
2376 /* parse substatements */
2377 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2378 switch (child->kw) {
2379 case LY_STMT_CONFIG:
2380 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
2381 break;
2382 case LY_STMT_DESCRIPTION:
2383 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
2384 break;
2385 case LY_STMT_IF_FEATURE:
2386 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
2387 break;
2388 case LY_STMT_REFERENCE:
2389 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
2390 break;
2391 case LY_STMT_STATUS:
2392 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
2393 break;
2394 case LY_STMT_WHEN:
2395 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
2396 break;
2397 case LY_STMT_PRESENCE:
2398 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
2399 break;
2400 case LY_STMT_ANYDATA:
2401 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
2402 /* fall through */
2403 case LY_STMT_ANYXML:
2404 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
2405 break;
2406 case LY_STMT_CHOICE:
2407 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
2408 break;
2409 case LY_STMT_CONTAINER:
2410 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
2411 break;
2412 case LY_STMT_LEAF:
2413 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
2414 break;
2415 case LY_STMT_LEAF_LIST:
2416 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
2417 break;
2418 case LY_STMT_LIST:
2419 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
2420 break;
2421 case LY_STMT_USES:
2422 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
2423 break;
2424
2425 case LY_STMT_TYPEDEF:
2426 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
2427 break;
2428 case LY_STMT_MUST:
2429 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
2430 break;
2431 case LY_STMT_ACTION:
2432 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
2433 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
2434 break;
2435 case LY_STMT_GROUPING:
2436 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
2437 break;
2438 case LY_STMT_NOTIFICATION:
2439 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
2440 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
2441 break;
2442 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002443 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002444 break;
2445 default:
2446 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "container");
2447 return LY_EVALID;
2448 }
2449 }
2450
2451 return LY_SUCCESS;
2452}
2453
2454/**
2455 * @brief Parse the list statement.
2456 *
2457 * @param[in] ctx parser context.
2458 * @param[in] stmt Source statement data from the parsed extension instance.
2459 * @param[in] parent Parent node to connect to (not into).
2460 * @param[in,out] siblings Siblings to add to.
2461 *
2462 * @return LY_ERR values.
2463 */
2464static LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +02002465lysp_stmt_list(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
2466 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002467{
2468 struct lysp_node_list *list;
2469
2470 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2471
2472 /* create new list structure */
2473 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
2474
2475 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
2476 list->nodetype = LYS_LIST;
2477 list->parent = parent;
2478
2479 /* parse substatements */
2480 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2481 switch (child->kw) {
2482 case LY_STMT_CONFIG:
2483 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
2484 break;
2485 case LY_STMT_DESCRIPTION:
2486 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
2487 break;
2488 case LY_STMT_IF_FEATURE:
2489 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
2490 break;
2491 case LY_STMT_REFERENCE:
2492 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
2493 break;
2494 case LY_STMT_STATUS:
2495 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
2496 break;
2497 case LY_STMT_WHEN:
2498 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
2499 break;
2500 case LY_STMT_KEY:
2501 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
2502 break;
2503 case LY_STMT_MAX_ELEMENTS:
2504 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
2505 break;
2506 case LY_STMT_MIN_ELEMENTS:
2507 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
2508 break;
2509 case LY_STMT_ORDERED_BY:
2510 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
2511 break;
2512 case LY_STMT_UNIQUE:
2513 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
2514 break;
2515
2516 case LY_STMT_ANYDATA:
2517 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
2518 /* fall through */
2519 case LY_STMT_ANYXML:
2520 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
2521 break;
2522 case LY_STMT_CHOICE:
2523 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
2524 break;
2525 case LY_STMT_CONTAINER:
2526 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
2527 break;
2528 case LY_STMT_LEAF:
2529 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
2530 break;
2531 case LY_STMT_LEAF_LIST:
2532 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
2533 break;
2534 case LY_STMT_LIST:
2535 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
2536 break;
2537 case LY_STMT_USES:
2538 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
2539 break;
2540
2541 case LY_STMT_TYPEDEF:
2542 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
2543 break;
2544 case LY_STMT_MUST:
2545 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
2546 break;
2547 case LY_STMT_ACTION:
2548 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
2549 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
2550 break;
2551 case LY_STMT_GROUPING:
2552 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
2553 break;
2554 case LY_STMT_NOTIFICATION:
2555 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
2556 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
2557 break;
2558 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002559 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002560 break;
2561 default:
2562 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "list");
2563 return LY_EVALID;
2564 }
2565 }
2566
2567 return LY_SUCCESS;
2568}
2569
Radek Krejci335332a2019-09-05 13:03:35 +02002570LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002571lysp_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 +02002572{
Radek Krejciad5963b2019-09-06 16:03:05 +02002573 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002574 uint16_t flags;
2575 struct lys_parser_ctx pctx = {0};
Michal Vasko8a67eff2021-12-07 14:04:47 +01002576 struct ly_set pmods = {0};
2577 void *objs;
Radek Krejci335332a2019-09-05 13:03:35 +02002578
Michal Vasko8a67eff2021-12-07 14:04:47 +01002579 /* local context */
Michal Vaskob36053d2020-03-26 15:49:30 +01002580 pctx.format = LYS_IN_YANG;
Michal Vasko8a67eff2021-12-07 14:04:47 +01002581 pctx.parsed_mods = &pmods;
2582 objs = &ctx->pmod;
2583 pmods.objs = objs;
2584 pmods.count = 1;
Radek Krejci2efc45b2020-12-22 16:25:44 +01002585
Radek Krejciddace2c2021-01-08 11:30:56 +01002586 LOG_LOCSET(NULL, NULL, ctx->path, NULL);
Radek Krejci335332a2019-09-05 13:03:35 +02002587
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002588 switch (stmt->kw) {
2589 case LY_STMT_ACTION:
2590 case LY_STMT_RPC:
2591 ret = lysp_stmt_action(&pctx, stmt, NULL, (struct lysp_node_action **)result);
2592 break;
2593 case LY_STMT_ANYDATA:
2594 case LY_STMT_ANYXML:
2595 ret = lysp_stmt_any(&pctx, stmt, NULL, (struct lysp_node **)result);
2596 break;
2597 case LY_STMT_AUGMENT:
2598 ret = lysp_stmt_augment(&pctx, stmt, NULL, (struct lysp_node_augment **)result);
2599 break;
2600 case LY_STMT_BASE:
2601 ret = lysp_stmt_text_fields(&pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
2602 break;
2603 case LY_STMT_BIT:
2604 case LY_STMT_ENUM:
2605 ret = lysp_stmt_type_enum(&pctx, stmt, (struct lysp_type_enum **)result);
2606 break;
2607 case LY_STMT_CASE:
2608 ret = lysp_stmt_case(&pctx, stmt, NULL, (struct lysp_node **)result);
2609 break;
2610 case LY_STMT_CHOICE:
2611 ret = lysp_stmt_choice(&pctx, stmt, NULL, (struct lysp_node **)result);
2612 break;
2613 case LY_STMT_CONFIG:
Michal Vasko39ed7a22022-02-21 08:34:18 +01002614 assert(*result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002615 ret = lysp_stmt_config(&pctx, stmt, *(uint16_t **)result, exts);
2616 break;
2617 case LY_STMT_CONTACT:
2618 case LY_STMT_DESCRIPTION:
2619 case LY_STMT_ERROR_APP_TAG:
2620 case LY_STMT_ERROR_MESSAGE:
2621 case LY_STMT_KEY:
2622 case LY_STMT_NAMESPACE:
2623 case LY_STMT_ORGANIZATION:
2624 case LY_STMT_PRESENCE:
2625 case LY_STMT_REFERENCE:
2626 case LY_STMT_UNITS:
2627 ret = lysp_stmt_text_field(&pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
2628 break;
2629 case LY_STMT_CONTAINER:
2630 ret = lysp_stmt_container(&pctx, stmt, NULL, (struct lysp_node **)result);
2631 break;
2632 case LY_STMT_DEFAULT:
2633 case LY_STMT_IF_FEATURE:
2634 case LY_STMT_UNIQUE:
2635 ret = lysp_stmt_qnames(&pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
2636 break;
2637 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002638 ret = lysp_stmt_ext(&pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002639 break;
2640 case LY_STMT_FRACTION_DIGITS:
2641 ret = lysp_stmt_type_fracdigits(&pctx, stmt, *(uint8_t **)result, exts);
2642 break;
2643 case LY_STMT_GROUPING:
2644 ret = lysp_stmt_grouping(&pctx, stmt, NULL, (struct lysp_node_grp **)result);
2645 break;
2646 case LY_STMT_INPUT:
2647 case LY_STMT_OUTPUT: {
2648 struct lysp_node_action_inout *inout;
2649
2650 *result = inout = calloc(1, sizeof *inout);
2651 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
2652 ret = lysp_stmt_inout(&pctx, stmt, NULL, inout);
2653 break;
2654 }
2655 case LY_STMT_LEAF:
2656 ret = lysp_stmt_leaf(&pctx, stmt, NULL, (struct lysp_node **)result);
2657 break;
2658 case LY_STMT_LEAF_LIST:
2659 ret = lysp_stmt_leaflist(&pctx, stmt, NULL, (struct lysp_node **)result);
2660 break;
2661 case LY_STMT_LENGTH:
2662 case LY_STMT_MUST:
2663 case LY_STMT_RANGE:
2664 ret = lysp_stmt_restrs(&pctx, stmt, (struct lysp_restr **)result);
2665 break;
2666 case LY_STMT_LIST:
2667 ret = lysp_stmt_list(&pctx, stmt, NULL, (struct lysp_node **)result);
2668 break;
2669 case LY_STMT_MANDATORY:
2670 ret = lysp_stmt_mandatory(&pctx, stmt, *(uint16_t **)result, exts);
2671 break;
2672 case LY_STMT_MAX_ELEMENTS:
2673 flags = 0;
2674 ret = lysp_stmt_maxelements(&pctx, stmt, *(uint32_t **)result, &flags, exts);
2675 break;
2676 case LY_STMT_MIN_ELEMENTS:
2677 flags = 0;
2678 ret = lysp_stmt_minelements(&pctx, stmt, *(uint32_t **)result, &flags, exts);
2679 break;
2680 case LY_STMT_MODIFIER:
2681 ret = lysp_stmt_type_pattern_modifier(&pctx, stmt, (const char **)result, exts);
2682 break;
2683 case LY_STMT_NOTIFICATION:
2684 ret = lysp_stmt_notif(&pctx, stmt, NULL, (struct lysp_node_notif **)result);
2685 break;
2686 case LY_STMT_ORDERED_BY:
2687 ret = lysp_stmt_orderedby(&pctx, stmt, *(uint16_t **)result, exts);
2688 break;
2689 case LY_STMT_PATH: {
2690 const char *str_path = NULL;
2691
2692 LY_CHECK_RET(lysp_stmt_text_field(&pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02002693 ret = ly_path_parse(ctx->ctx, NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002694 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
2695 lydict_remove(ctx->ctx, str_path);
2696 break;
2697 }
2698 case LY_STMT_PATTERN:
2699 ret = lysp_stmt_type_pattern(&pctx, stmt, (struct lysp_restr **)result);
2700 break;
2701 case LY_STMT_POSITION:
2702 case LY_STMT_VALUE:
2703 flags = 0;
2704 ret = lysp_stmt_type_enum_value_pos(&pctx, stmt, *(int64_t **)result, &flags, exts);
2705 break;
2706 case LY_STMT_PREFIX:
2707 ret = lysp_stmt_text_field(&pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
2708 break;
2709 case LY_STMT_REFINE:
2710 ret = lysp_stmt_refine(&pctx, stmt, (struct lysp_refine **)result);
2711 break;
2712 case LY_STMT_REQUIRE_INSTANCE:
2713 flags = 0;
2714 ret = lysp_stmt_type_reqinstance(&pctx, stmt, *(uint8_t **)result, &flags, exts);
2715 break;
Michal Vasko69730152020-10-09 16:30:07 +02002716 case LY_STMT_STATUS:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002717 ret = lysp_stmt_status(&pctx, stmt, *(uint16_t **)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02002718 break;
Radek Krejci335332a2019-09-05 13:03:35 +02002719 case LY_STMT_TYPE: {
2720 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02002721
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002722 *result = type = calloc(1, sizeof *type);
2723 LY_CHECK_ERR_RET(!type, LOGMEM(ctx->ctx), LY_EMEM);
2724 ret = lysp_stmt_type(&pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02002725 break;
Radek Krejci0f969882020-08-21 16:56:47 +02002726 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002727 case LY_STMT_TYPEDEF:
2728 ret = lysp_stmt_typedef(&pctx, stmt, NULL, (struct lysp_tpdf **)result);
2729 break;
2730 case LY_STMT_USES:
2731 ret = lysp_stmt_uses(&pctx, stmt, NULL, (struct lysp_node **)result);
2732 break;
2733 case LY_STMT_WHEN:
2734 ret = lysp_stmt_when(&pctx, stmt, (struct lysp_when **)result);
2735 break;
Radek Krejci335332a2019-09-05 13:03:35 +02002736 default:
2737 LOGINT(ctx->ctx);
2738 return LY_EINT;
2739 }
2740
Radek Krejciddace2c2021-01-08 11:30:56 +01002741 LOG_LOCBACK(0, 0, 1, 0);
Radek Krejciad5963b2019-09-06 16:03:05 +02002742 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02002743}
Michal Vasko59892dd2022-05-13 11:02:30 +02002744
2745void
2746lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
2747{
2748 char path[PATH_MAX];
2749
2750#ifndef __APPLE__
2751 char proc_path[32];
2752 int len;
2753#endif
2754
2755 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
2756 if (*filepath) {
2757 /* filepath already set */
2758 return;
2759 }
2760
2761 switch (in->type) {
2762 case LY_IN_FILEPATH:
2763 if (realpath(in->method.fpath.filepath, path) != NULL) {
2764 lydict_insert(ctx, path, 0, filepath);
2765 } else {
2766 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
2767 }
2768
2769 break;
2770 case LY_IN_FD:
2771#ifdef __APPLE__
2772 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
2773 lydict_insert(ctx, path, 0, filepath);
2774 }
2775#elif defined _WIN32
2776 HANDLE h = _get_osfhandle(in->method.fd);
2777 FILE_NAME_INFO info;
2778 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
2779 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
2780 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
2781 lydict_insert(ctx, buf, len, filepath);
2782 }
2783#else
2784 /* get URI if there is /proc */
2785 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
2786 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
2787 lydict_insert(ctx, path, len, filepath);
2788 }
2789#endif
2790 break;
2791 case LY_IN_MEMORY:
2792 case LY_IN_FILE:
2793 /* nothing to do */
2794 break;
2795 default:
2796 LOGINT(ctx);
2797 break;
2798 }
2799}