blob: 4a0e421fb3c670dbaffeebc4c656db201c1b3817 [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"
Michal Vaskob4750962022-10-06 15:33:35 +020048#include "plugins_exts/metadata.h"
Radek Krejci77114102021-03-10 15:21:57 +010049#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020050#include "tree.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020051#include "tree_data.h"
52#include "tree_data_internal.h"
Radek Krejci335332a2019-09-05 13:03:35 +020053#include "tree_schema.h"
54#include "tree_schema_internal.h"
55
Michal Vasko59892dd2022-05-13 11:02:30 +020056void
57lyd_ctx_free(struct lyd_ctx *lydctx)
58{
59 ly_set_erase(&lydctx->node_types, NULL);
60 ly_set_erase(&lydctx->meta_types, NULL);
61 ly_set_erase(&lydctx->node_when, NULL);
Michal Vasko135719f2022-08-25 12:18:17 +020062 ly_set_erase(&lydctx->ext_node, free);
Michal Vasko59892dd2022-05-13 11:02:30 +020063 ly_set_erase(&lydctx->ext_val, free);
64}
65
66LY_ERR
67lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op)
68{
69 const struct lyd_node *iter;
70
71 *op = NULL;
72
73 if (!parent) {
74 /* no parent, nothing to look for */
75 return LY_SUCCESS;
76 }
77
78 /* we need to find the operation node if it already exists */
79 for (iter = parent; iter; iter = lyd_parent(iter)) {
80 if (iter->schema && (iter->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
81 break;
82 }
83 }
84
85 if (!iter) {
86 /* no operation found */
87 return LY_SUCCESS;
88 }
89
90 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
91 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
92 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
93 return LY_EINVAL;
94 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
95 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
96 iter->schema->name);
97 return LY_EINVAL;
98 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
99 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
100 iter->schema->name);
101 return LY_EINVAL;
102 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
103 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
104 iter->schema->name);
105 return LY_EINVAL;
106 }
107
108 *op = (struct lyd_node *)iter;
109 return LY_SUCCESS;
110}
111
112LY_ERR
113lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
114{
115 LY_ERR rc = LY_SUCCESS;
116
117 LOG_LOCSET(snode, NULL, NULL, NULL);
118
119 if (lydctx->int_opts & LYD_INTOPT_ANY) {
120 /* nothing to check, everything is allowed */
121 goto cleanup;
122 }
123
124 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
125 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
126 rc = LY_EVALID;
127 goto cleanup;
128 }
129
130 if (snode->nodetype == LYS_RPC) {
131 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
132 if (lydctx->op_node) {
133 goto error_node_dup;
134 }
135 } else {
136 goto error_node_inval;
137 }
138 } else if (snode->nodetype == LYS_ACTION) {
139 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
140 if (lydctx->op_node) {
141 goto error_node_dup;
142 }
143 } else {
144 goto error_node_inval;
145 }
146 } else if (snode->nodetype == LYS_NOTIF) {
147 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
148 if (lydctx->op_node) {
149 goto error_node_dup;
150 }
151 } else {
152 goto error_node_inval;
153 }
154 }
155
156 /* success */
157 goto cleanup;
158
159error_node_dup:
160 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
161 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
162 lydctx->op_node->schema->name);
163 rc = LY_EVALID;
164 goto cleanup;
165
166error_node_inval:
167 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
168 snode->name);
169 rc = LY_EVALID;
170
171cleanup:
172 LOG_LOCBACK(1, 0, 0, 0);
173 return rc;
174}
175
176LY_ERR
177lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
178 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
179{
180 ly_bool incomplete;
181
182 LY_CHECK_RET(lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node));
183
184 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
185 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
186 }
187 return LY_SUCCESS;
188}
189
190LY_ERR
191lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
192 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
193 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
194{
195 ly_bool incomplete;
196 struct lyd_meta *first = NULL;
197
198 if (meta && *meta) {
199 /* remember the first metadata */
200 first = *meta;
201 }
202
203 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
204 hints, ctx_node, 0, &incomplete));
205
206 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
207 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
208 }
209
210 if (first) {
211 /* always return the first metadata */
212 *meta = first;
213 }
214
215 return LY_SUCCESS;
216}
217
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200218LY_ERR
219lyd_parse_check_keys(struct lyd_node *node)
220{
221 const struct lysc_node *skey = NULL;
222 const struct lyd_node *key;
223
224 assert(node->schema->nodetype == LYS_LIST);
225
226 key = lyd_child(node);
227 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
228 if (!key || (key->schema != skey)) {
229 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
230 return LY_EVALID;
231 }
232
233 key = key->next;
234 }
235
236 return LY_SUCCESS;
237}
238
239LY_ERR
240lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
241 struct lysc_ext_instance *ext)
242{
243 struct lyd_meta *meta2, *prev_meta = NULL;
244 struct lyd_ctx_ext_val *ext_val;
245
246 if (lysc_has_when(node->schema)) {
247 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
248 /* remember we need to evaluate this node's when */
249 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
250 }
251 }
252
253 LY_LIST_FOR(*meta, meta2) {
254 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
255 meta2->value.boolean) {
256 /* node is default according to the metadata */
257 node->flags |= LYD_DEFAULT;
258
259 /* delete the metadata */
260 if (prev_meta) {
261 prev_meta->next = meta2->next;
262 } else {
263 *meta = (*meta)->next;
264 }
265 lyd_free_meta_single(meta2);
266 break;
267 }
268
269 prev_meta = meta2;
270 }
271
272 if (ext) {
273 /* parsed for an extension */
274 node->flags |= LYD_EXT;
275
276 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
277 /* rememeber for validation */
278 ext_val = malloc(sizeof *ext_val);
279 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
280 ext_val->ext = ext;
281 ext_val->sibling = node;
282 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
283 }
284 }
285
286 return LY_SUCCESS;
287}
288
Michal Vaskod0625d72022-10-06 15:02:50 +0200289static LY_ERR lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100290 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200291static LY_ERR lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100292 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200293static LY_ERR lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100294 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200295static LY_ERR lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100296 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200297static LY_ERR lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100298 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200299static LY_ERR lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100300 struct lysp_node **siblings);
301
Radek Krejci335332a2019-09-05 13:03:35 +0200302static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200303lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200304{
Radek Krejci857189e2020-09-01 13:26:36 +0200305 uint8_t prefix = 0;
306 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200307 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200308 size_t utf8_char_len;
309
310 while (*val) {
311 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200312 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200313
314 switch (val_type) {
315 case Y_IDENTIF_ARG:
316 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
317 break;
318 case Y_PREF_IDENTIF_ARG:
319 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
320 break;
321 case Y_STR_ARG:
322 case Y_MAYBE_STR_ARG:
323 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
324 break;
325 }
326 first = 0;
327 }
328
329 return LY_SUCCESS;
330}
331
332/**
333 * @brief Parse extension instance.
334 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100335 * @param[in] ctx parser context.
336 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100337 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200338 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
339 * @param[in,out] exts Extension instances to add to.
340 *
341 * @return LY_ERR values.
342 */
343static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200344lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200345 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200346{
347 struct lysp_ext_instance *e;
348
Michal Vaskob36053d2020-03-26 15:49:30 +0100349 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200350
351 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200352 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100353 e->parent_stmt = insubstmt;
354 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200355 e->parsed = NULL;
Radek Krejci335332a2019-09-05 13:03:35 +0200356 /* TODO (duplicate) e->child = stmt->child; */
357
358 /* get optional argument */
359 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200360 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200361 }
362
363 return LY_SUCCESS;
364}
365
366/**
367 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
368 * description, etc...
369 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100370 * @param[in] ctx parser context.
371 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200372 * @param[in] substmt_index Index of this substatement.
373 * @param[in,out] value Place to store the parsed value.
374 * @param[in] arg Type of the YANG keyword argument (of the value).
375 * @param[in,out] exts Extension instances to add to.
376 *
377 * @return LY_ERR values.
378 */
379static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200380lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index,
Radek Krejci0f969882020-08-21 16:56:47 +0200381 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200382{
Radek Krejci335332a2019-09-05 13:03:35 +0200383 if (*value) {
Radek Krejci3972b332021-03-02 16:34:31 +0100384 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200385 return LY_EVALID;
386 }
387
388 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200389 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200390
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100391 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
392 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200393 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100394 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200395 break;
396 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100397 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200398 return LY_EVALID;
399 }
400 }
401 return LY_SUCCESS;
402}
403
404/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200405 * @brief Parse a qname that can have more instances such as if-feature.
406 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100407 * @param[in] ctx parser context.
408 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200409 * @param[in,out] qnames Parsed qnames to add to.
410 * @param[in] arg Type of the expected argument.
411 * @param[in,out] exts Extension instances to add to.
412 *
413 * @return LY_ERR values.
414 */
415static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200416lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt,
Michal Vasko7f45cf22020-10-01 12:49:44 +0200417 struct lysp_qname **qnames, enum yang_arg arg, struct lysp_ext_instance **exts)
418{
419 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200420
421 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
422
423 /* allocate new pointer */
424 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
425 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100426 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200427
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100428 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
429 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200430 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100431 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200432 break;
433 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100434 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200435 return LY_EVALID;
436 }
437 }
438 return LY_SUCCESS;
439}
440
441/**
Radek Krejci335332a2019-09-05 13:03:35 +0200442 * @brief Parse a generic text field that can have more instances such as base.
443 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100444 * @param[in] ctx parser context.
445 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200446 * @param[in,out] texts Parsed values to add to.
447 * @param[in] arg Type of the expected argument.
448 * @param[in,out] exts Extension instances to add to.
449 *
450 * @return LY_ERR values.
451 */
452static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200453lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200454 const char ***texts, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200455{
456 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200457
458 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
459
460 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100461 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200462 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200463
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100464 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
465 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200466 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100467 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200468 break;
469 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100470 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200471 return LY_EVALID;
472 }
473 }
474 return LY_SUCCESS;
475}
476
477/**
478 * @brief Parse the status statement.
479 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100480 * @param[in] ctx parser context.
481 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200482 * @param[in,out] flags Flags to add to.
483 * @param[in,out] exts Extension instances to add to.
484 *
485 * @return LY_ERR values.
486 */
487static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200488lysp_stmt_status(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200489{
490 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200491
492 if (*flags & LYS_STATUS_MASK) {
493 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
494 return LY_EVALID;
495 }
496
497 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
498 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100499 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200500 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100501 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200502 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100503 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200504 *flags |= LYS_STATUS_OBSLT;
505 } else {
506 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
507 return LY_EVALID;
508 }
509
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100510 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
511 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200512 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100513 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200514 break;
515 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100516 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200517 return LY_EVALID;
518 }
519 }
520 return LY_SUCCESS;
521}
522
523/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100524 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200525 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100526 * @param[in] ctx parser context.
527 * @param[in] stmt Source statement data from the parsed extension instance.
528 * @param[in,out] when_p When pointer to parse to.
529 *
530 * @return LY_ERR values.
531 */
532static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200533lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100534{
535 LY_ERR ret = LY_SUCCESS;
536 struct lysp_when *when;
537
538 if (*when_p) {
539 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
540 return LY_EVALID;
541 }
542
543 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
544
545 when = calloc(1, sizeof *when);
546 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
547 *when_p = when;
548
549 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
550
551 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
552 switch (child->kw) {
553 case LY_STMT_DESCRIPTION:
554 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
555 break;
556 case LY_STMT_REFERENCE:
557 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
558 break;
559 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100560 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100561 break;
562 default:
563 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "when");
564 return LY_EVALID;
565 }
566 }
567 return ret;
568}
569
570/**
571 * @brief Parse the config statement.
572 *
573 * @param[in] ctx parser context.
574 * @param[in] stmt Source statement data from the parsed extension instance.
575 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200576 * @param[in,out] exts Extension instances to add to.
577 *
578 * @return LY_ERR values.
579 */
580static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200581lysp_stmt_config(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200582{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100583 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200584
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100585 if (*flags & LYS_CONFIG_MASK) {
586 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
587 return LY_EVALID;
588 }
589
590 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
591 arg_len = strlen(stmt->arg);
592 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
593 *flags |= LYS_CONFIG_W;
594 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
595 *flags |= LYS_CONFIG_R;
596 } else {
597 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
598 return LY_EVALID;
599 }
600
601 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
602 switch (child->kw) {
603 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100604 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100605 break;
606 default:
607 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "config");
608 return LY_EVALID;
609 }
610 }
611
612 return LY_SUCCESS;
613}
614
615/**
616 * @brief Parse the mandatory statement.
617 *
618 * @param[in] ctx parser context.
619 * @param[in] stmt Source statement data from the parsed extension instance.
620 * @param[in,out] flags Flags to add to.
621 * @param[in,out] exts Extension instances to add to.
622 *
623 * @return LY_ERR values.
624 */
625static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200626lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200627 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100628{
629 size_t arg_len;
630
631 if (*flags & LYS_MAND_MASK) {
632 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
633 return LY_EVALID;
634 }
635
636 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
637 arg_len = strlen(stmt->arg);
638 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
639 *flags |= LYS_MAND_TRUE;
640 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
641 *flags |= LYS_MAND_FALSE;
642 } else {
643 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
644 return LY_EVALID;
645 }
646
647 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
648 switch (child->kw) {
649 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100650 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100651 break;
652 default:
653 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "mandatory");
654 return LY_EVALID;
655 }
656 }
657
658 return LY_SUCCESS;
659}
660
661/**
662 * @brief Parse a restriction such as range or length.
663 *
664 * @param[in] ctx parser context.
665 * @param[in] stmt Source statement data from the parsed extension instance.
666 * @param[in,out] exts Extension instances to add to.
667 *
668 * @return LY_ERR values.
669 */
670static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200671lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100672{
Radek Krejci335332a2019-09-05 13:03:35 +0200673 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200674 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100675 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200676
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100677 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
678 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200679 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100680 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200681 break;
682 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100683 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200684 break;
685 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100686 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200687 break;
688 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100689 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200690 break;
691 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100692 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200693 break;
694 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100695 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200696 return LY_EVALID;
697 }
698 }
699 return LY_SUCCESS;
700}
701
702/**
703 * @brief Parse a restriction that can have more instances such as must.
704 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100705 * @param[in] ctx parser context.
706 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200707 * @param[in,out] restrs Restrictions to add to.
708 *
709 * @return LY_ERR values.
710 */
711static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200712lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200713{
714 struct lysp_restr *restr;
715
Michal Vaskob36053d2020-03-26 15:49:30 +0100716 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100717 return lysp_stmt_restr(ctx, stmt, restr);
718}
719
720/**
721 * @brief Parse the anydata or anyxml statement.
722 *
723 * @param[in] ctx parser context.
724 * @param[in] stmt Source statement data from the parsed extension instance.
725 * @param[in,out] siblings Siblings to add to.
726 *
727 * @return LY_ERR values.
728 */
729static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200730lysp_stmt_any(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100731{
732 struct lysp_node_anydata *any;
733
734 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
735
736 /* create new structure and insert into siblings */
737 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
738
739 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
740 any->parent = parent;
741
742 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
743
744 /* parse substatements */
745 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
746 switch (child->kw) {
747 case LY_STMT_CONFIG:
748 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
749 break;
750 case LY_STMT_DESCRIPTION:
751 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
752 break;
753 case LY_STMT_IF_FEATURE:
754 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
755 break;
756 case LY_STMT_MANDATORY:
757 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
758 break;
759 case LY_STMT_MUST:
760 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
761 break;
762 case LY_STMT_REFERENCE:
763 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
764 break;
765 case LY_STMT_STATUS:
766 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
767 break;
768 case LY_STMT_WHEN:
769 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
770 break;
771 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100772 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100773 break;
774 default:
775 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
776 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(LY_STMT_ANYDATA) : ly_stmt2str(LY_STMT_ANYXML));
777 return LY_EVALID;
778 }
779 }
780
781 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200782}
783
784/**
785 * @brief Parse the value or position statement. Substatement of type enum statement.
786 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100787 * @param[in] ctx parser context.
788 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200789 * @param[in,out] value Value to write to.
790 * @param[in,out] flags Flags to write to.
791 * @param[in,out] exts Extension instances to add to.
792 *
793 * @return LY_ERR values.
794 */
795static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200796lysp_stmt_type_enum_value_pos(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, int64_t *value, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +0200797 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200798{
799 size_t arg_len;
800 char *ptr = NULL;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200801 long long int num = 0;
802 unsigned long long int unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200803
804 if (*flags & LYS_SET_VALUE) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100805 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200806 return LY_EVALID;
807 }
808 *flags |= LYS_SET_VALUE;
809
810 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
811
812 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100813 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
814 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
815 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200816 goto error;
817 }
818
819 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100820 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200821 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200822 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100823 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200824 goto error;
825 }
826 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200827 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200828 if (unum > UINT64_C(4294967295)) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100829 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200830 goto error;
831 }
832 }
833 /* we have not parsed the whole argument */
834 if ((size_t)(ptr - stmt->arg) != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100835 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200836 goto error;
837 }
838 if (errno == ERANGE) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100839 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200840 goto error;
841 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100842 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200843 *value = num;
844 } else {
845 *value = unum;
846 }
847
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100848 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
849 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200850 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100851 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 +0200852 break;
853 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100854 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200855 return LY_EVALID;
856 }
857 }
858 return LY_SUCCESS;
859
860error:
861 return LY_EVALID;
862}
863
864/**
865 * @brief Parse the enum or bit statement. Substatement of type statement.
866 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100867 * @param[in] ctx parser context.
868 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200869 * @param[in,out] enums Enums or bits to add to.
870 *
871 * @return LY_ERR values.
872 */
873static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200874lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +0200875{
876 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200877
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100878 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 +0200879
Michal Vaskob36053d2020-03-26 15:49:30 +0100880 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200881
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100882 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +0200883 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
884 } /* else nothing specific for YANG_BIT */
885
Radek Krejci011e4aa2020-09-04 15:22:31 +0200886 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100887 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +0200888
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100889 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
890 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200891 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100892 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200893 break;
894 case LY_STMT_IF_FEATURE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100895 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(stmt->kw));
896 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200897 break;
898 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100899 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200900 break;
901 case LY_STMT_STATUS:
902 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
903 break;
904 case LY_STMT_VALUE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100905 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
906 ly_stmt2str(stmt->kw)), LY_EVALID);
907 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200908 break;
909 case LY_STMT_POSITION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100910 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
911 ly_stmt2str(stmt->kw)), LY_EVALID);
912 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200913 break;
914 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100915 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200916 break;
917 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100918 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200919 return LY_EVALID;
920 }
921 }
922 return LY_SUCCESS;
923}
924
925/**
926 * @brief Parse the fraction-digits statement. Substatement of type statement.
927 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100928 * @param[in] ctx parser context.
929 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200930 * @param[in,out] fracdig Value to write to.
931 * @param[in,out] exts Extension instances to add to.
932 *
933 * @return LY_ERR values.
934 */
935static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200936lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +0200937 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200938{
939 char *ptr;
940 size_t arg_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200941 unsigned long long int num;
Radek Krejci335332a2019-09-05 13:03:35 +0200942
943 if (*fracdig) {
944 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
945 return LY_EVALID;
946 }
947
948 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
949 arg_len = strlen(stmt->arg);
950 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
951 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
952 return LY_EVALID;
953 }
954
955 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200956 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200957 /* we have not parsed the whole argument */
958 if ((size_t)(ptr - stmt->arg) != arg_len) {
959 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
960 return LY_EVALID;
961 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100962 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200963 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
964 return LY_EVALID;
965 }
966 *fracdig = num;
967
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100968 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
969 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200970 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100971 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200972 break;
973 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100974 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +0200975 return LY_EVALID;
976 }
977 }
978 return LY_SUCCESS;
979}
980
981/**
982 * @brief Parse the require-instance statement. Substatement of type statement.
983 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100984 * @param[in] ctx parser context.
985 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200986 * @param[in,out] reqinst Value to write to.
987 * @param[in,out] flags Flags to write to.
988 * @param[in,out] exts Extension instances to add to.
989 *
990 * @return LY_ERR values.
991 */
992static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200993lysp_stmt_type_reqinstance(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *reqinst, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +0200994 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200995{
996 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200997
998 if (*flags & LYS_SET_REQINST) {
999 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1000 return LY_EVALID;
1001 }
1002 *flags |= LYS_SET_REQINST;
1003
1004 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1005 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001006 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001007 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001008 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001009 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1010 return LY_EVALID;
1011 }
1012
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001013 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1014 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001015 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001016 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001017 break;
1018 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001019 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001020 return LY_EVALID;
1021 }
1022 }
1023 return LY_SUCCESS;
1024}
1025
1026/**
1027 * @brief Parse the modifier statement. Substatement of type pattern statement.
1028 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001029 * @param[in] ctx parser context.
1030 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001031 * @param[in,out] pat Value to write to.
1032 * @param[in,out] exts Extension instances to add to.
1033 *
1034 * @return LY_ERR values.
1035 */
1036static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001037lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001038 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001039{
1040 size_t arg_len;
1041 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001042
Radek Krejcif13b87b2020-12-01 22:02:17 +01001043 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001044 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1045 return LY_EVALID;
1046 }
1047
1048 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1049 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001050 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001051 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1052 return LY_EVALID;
1053 }
1054
1055 /* replace the value in the dictionary */
1056 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001057 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001058 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001059 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001060
Radek Krejcif13b87b2020-12-01 22:02:17 +01001061 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1062 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001063 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001064
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001065 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1066 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001067 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001068 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001069 break;
1070 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001071 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001072 return LY_EVALID;
1073 }
1074 }
1075 return LY_SUCCESS;
1076}
1077
1078/**
1079 * @brief Parse the pattern statement. Substatement of type statement.
1080 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001081 * @param[in] ctx parser context.
1082 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001083 * @param[in,out] patterns Restrictions to add to.
1084 *
1085 * @return LY_ERR values.
1086 */
1087static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001088lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001089{
1090 char *buf;
1091 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001092 struct lysp_restr *restr;
1093
1094 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001095 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001096 arg_len = strlen(stmt->arg);
1097
1098 /* add special meaning first byte */
1099 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001100 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001101 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001102 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001103 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001104 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001105 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001106
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001107 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1108 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001109 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001110 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001111 break;
1112 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001113 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001114 break;
1115 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001116 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001117 break;
1118 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001119 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001120 break;
1121 case LY_STMT_MODIFIER:
1122 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001123 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001124 break;
1125 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001126 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001127 break;
1128 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001129 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001130 return LY_EVALID;
1131 }
1132 }
1133 return LY_SUCCESS;
1134}
1135
1136/**
1137 * @brief Parse the type statement.
1138 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001139 * @param[in] ctx parser context.
1140 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001141 * @param[in,out] type Type to wrote to.
1142 *
1143 * @return LY_ERR values.
1144 */
1145static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001146lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001147{
1148 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001149 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001150 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001151
1152 if (type->name) {
1153 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1154 return LY_EVALID;
1155 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001156
1157 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001158 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001159 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001160
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001161 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1162 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001163 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001164 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001165 type->flags |= LYS_SET_BASE;
1166 break;
1167 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001168 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001169 type->flags |= LYS_SET_BIT;
1170 break;
1171 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001172 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001173 type->flags |= LYS_SET_ENUM;
1174 break;
1175 case LY_STMT_FRACTION_DIGITS:
1176 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1177 type->flags |= LYS_SET_FRDIGITS;
1178 break;
1179 case LY_STMT_LENGTH:
1180 if (type->length) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001181 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001182 return LY_EVALID;
1183 }
1184 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001185 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001186
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001187 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001188 type->flags |= LYS_SET_LENGTH;
1189 break;
1190 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001191 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001192 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001193 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001194 lydict_remove(PARSER_CTX(ctx), str_path);
1195 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001196 type->flags |= LYS_SET_PATH;
1197 break;
1198 case LY_STMT_PATTERN:
1199 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1200 type->flags |= LYS_SET_PATTERN;
1201 break;
1202 case LY_STMT_RANGE:
1203 if (type->range) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001204 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001205 return LY_EVALID;
1206 }
1207 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001208 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001209
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001210 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001211 type->flags |= LYS_SET_RANGE;
1212 break;
1213 case LY_STMT_REQUIRE_INSTANCE:
1214 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001215 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001216 break;
1217 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001218 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001219 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1220 type->flags |= LYS_SET_TYPE;
1221 break;
1222 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001223 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001224 break;
1225 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001226 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001227 return LY_EVALID;
1228 }
1229 }
1230 return LY_SUCCESS;
1231}
1232
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001233/**
1234 * @brief Parse the leaf statement.
1235 *
1236 * @param[in] ctx parser context.
1237 * @param[in] stmt Source statement data from the parsed extension instance.
1238 * @param[in] parent Parent node to connect to (not into).
1239 * @param[in,out] siblings Siblings to add to.
1240 *
1241 * @return LY_ERR values.
1242 */
1243static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001244lysp_stmt_leaf(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent, struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001245{
1246 struct lysp_node_leaf *leaf;
1247
1248 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1249
1250 /* create new leaf structure */
1251 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1252 leaf->nodetype = LYS_LEAF;
1253 leaf->parent = parent;
1254
1255 /* get name */
1256 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1257
1258 /* parse substatements */
1259 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1260 switch (child->kw) {
1261 case LY_STMT_CONFIG:
1262 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1263 break;
1264 case LY_STMT_DEFAULT:
1265 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 +01001266 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001267 break;
1268 case LY_STMT_DESCRIPTION:
1269 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1270 break;
1271 case LY_STMT_IF_FEATURE:
1272 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1273 break;
1274 case LY_STMT_MANDATORY:
1275 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1276 break;
1277 case LY_STMT_MUST:
1278 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1279 break;
1280 case LY_STMT_REFERENCE:
1281 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1282 break;
1283 case LY_STMT_STATUS:
1284 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1285 break;
1286 case LY_STMT_TYPE:
1287 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1288 break;
1289 case LY_STMT_UNITS:
1290 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1291 break;
1292 case LY_STMT_WHEN:
1293 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1294 break;
1295 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001296 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001297 break;
1298 default:
1299 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "leaf");
1300 return LY_EVALID;
1301 }
1302 }
1303
1304 /* mandatory substatements */
1305 if (!leaf->type.name) {
1306 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1307 return LY_EVALID;
1308 }
1309
1310 return LY_SUCCESS;
1311}
1312
1313/**
1314 * @brief Parse the max-elements statement.
1315 *
1316 * @param[in] ctx parser context.
1317 * @param[in] stmt Source statement data from the parsed extension instance.
1318 * @param[in,out] max Value to write to.
1319 * @param[in,out] flags Flags to write to.
1320 * @param[in,out] exts Extension instances to add to.
1321 *
1322 * @return LY_ERR values.
1323 */
1324static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001325lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001326 uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
1327{
1328 size_t arg_len;
1329 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001330 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001331
1332 if (*flags & LYS_SET_MAX) {
1333 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1334 return LY_EVALID;
1335 }
1336 *flags |= LYS_SET_MAX;
1337
1338 /* get value */
1339 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1340 arg_len = strlen(stmt->arg);
1341
1342 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1343 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1344 return LY_EVALID;
1345 }
1346
1347 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1348 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001349 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001350 /* we have not parsed the whole argument */
1351 if ((size_t)(ptr - stmt->arg) != arg_len) {
1352 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1353 return LY_EVALID;
1354 }
1355 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1356 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1357 return LY_EVALID;
1358 }
1359
1360 *max = num;
1361 } else {
1362 /* unbounded */
1363 *max = 0;
1364 }
1365
1366 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1367 switch (child->kw) {
1368 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001369 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001370 break;
1371 default:
1372 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "max-elements");
1373 return LY_EVALID;
1374 }
1375 }
1376
1377 return LY_SUCCESS;
1378}
1379
1380/**
1381 * @brief Parse the min-elements statement.
1382 *
1383 * @param[in] ctx parser context.
1384 * @param[in] stmt Source statement data from the parsed extension instance.
1385 * @param[in,out] min Value to write to.
1386 * @param[in,out] flags Flags to write to.
1387 * @param[in,out] exts Extension instances to add to.
1388 *
1389 * @return LY_ERR values.
1390 */
1391static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001392lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001393 uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
1394{
1395 size_t arg_len;
1396 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001397 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001398
1399 if (*flags & LYS_SET_MIN) {
1400 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
1401 return LY_EVALID;
1402 }
1403 *flags |= LYS_SET_MIN;
1404
1405 /* get value */
1406 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1407 arg_len = strlen(stmt->arg);
1408
1409 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
1410 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1411 return LY_EVALID;
1412 }
1413
1414 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001415 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001416 /* we have not parsed the whole argument */
1417 if ((size_t)(ptr - stmt->arg) != arg_len) {
1418 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1419 return LY_EVALID;
1420 }
1421 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1422 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
1423 return LY_EVALID;
1424 }
1425 *min = num;
1426
1427 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1428 switch (child->kw) {
1429 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001430 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001431 break;
1432 default:
1433 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "min-elements");
1434 return LY_EVALID;
1435 }
1436 }
1437
1438 return LY_SUCCESS;
1439}
1440
1441/**
1442 * @brief Parse the ordered-by statement.
1443 *
1444 * @param[in] ctx parser context.
1445 * @param[in] stmt Source statement data from the parsed extension instance.
1446 * @param[in,out] flags Flags to write to.
1447 * @param[in,out] exts Extension instances to add to.
1448 *
1449 * @return LY_ERR values.
1450 */
1451static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001452lysp_stmt_orderedby(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001453{
1454 size_t arg_len;
1455
1456 if (*flags & LYS_ORDBY_MASK) {
1457 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
1458 return LY_EVALID;
1459 }
1460
1461 /* get value */
1462 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1463 arg_len = strlen(stmt->arg);
1464 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
1465 *flags |= LYS_MAND_TRUE;
1466 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
1467 *flags |= LYS_MAND_FALSE;
1468 } else {
1469 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
1470 return LY_EVALID;
1471 }
1472
1473 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1474 switch (child->kw) {
1475 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001476 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001477 break;
1478 default:
1479 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "ordered-by");
1480 return LY_EVALID;
1481 }
1482 }
1483
1484 return LY_SUCCESS;
1485}
1486
1487/**
1488 * @brief Parse the leaf-list statement.
1489 *
1490 * @param[in] ctx parser context.
1491 * @param[in] stmt Source statement data from the parsed extension instance.
1492 * @param[in] parent Parent node to connect to (not into).
1493 * @param[in,out] siblings Siblings to add to.
1494 *
1495 * @return LY_ERR values.
1496 */
1497static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001498lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02001499 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001500{
1501 struct lysp_node_leaflist *llist;
1502
1503 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1504
1505 /* create new leaf-list structure */
1506 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
1507 llist->nodetype = LYS_LEAFLIST;
1508 llist->parent = parent;
1509
1510 /* get name */
1511 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
1512
1513 /* parse substatements */
1514 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1515 switch (child->kw) {
1516 case LY_STMT_CONFIG:
1517 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
1518 break;
1519 case LY_STMT_DEFAULT:
1520 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
1521 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
1522 break;
1523 case LY_STMT_DESCRIPTION:
1524 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
1525 break;
1526 case LY_STMT_IF_FEATURE:
1527 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
1528 break;
1529 case LY_STMT_MAX_ELEMENTS:
1530 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
1531 break;
1532 case LY_STMT_MIN_ELEMENTS:
1533 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
1534 break;
1535 case LY_STMT_MUST:
1536 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
1537 break;
1538 case LY_STMT_ORDERED_BY:
1539 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
1540 break;
1541 case LY_STMT_REFERENCE:
1542 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
1543 break;
1544 case LY_STMT_STATUS:
1545 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
1546 break;
1547 case LY_STMT_TYPE:
1548 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
1549 break;
1550 case LY_STMT_UNITS:
1551 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
1552 break;
1553 case LY_STMT_WHEN:
1554 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
1555 break;
1556 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001557 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001558 break;
1559 default:
1560 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "llist");
1561 return LY_EVALID;
1562 }
1563 }
1564
1565 /* mandatory substatements */
1566 if (!llist->type.name) {
1567 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
1568 return LY_EVALID;
1569 }
1570
1571 return LY_SUCCESS;
1572}
1573
1574/**
1575 * @brief Parse the refine statement.
1576 *
1577 * @param[in] ctx parser context.
1578 * @param[in] stmt Source statement data from the parsed extension instance.
1579 * @param[in,out] refines Refines to add to.
1580 *
1581 * @return LY_ERR values.
1582 */
1583static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001584lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001585{
1586 struct lysp_refine *rf;
1587
1588 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1589
1590 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
1591
1592 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
1593
1594 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1595 switch (child->kw) {
1596 case LY_STMT_CONFIG:
1597 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
1598 break;
1599 case LY_STMT_DEFAULT:
1600 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
1601 break;
1602 case LY_STMT_DESCRIPTION:
1603 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
1604 break;
1605 case LY_STMT_IF_FEATURE:
1606 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
1607 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
1608 break;
1609 case LY_STMT_MAX_ELEMENTS:
1610 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
1611 break;
1612 case LY_STMT_MIN_ELEMENTS:
1613 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
1614 break;
1615 case LY_STMT_MUST:
1616 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
1617 break;
1618 case LY_STMT_MANDATORY:
1619 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
1620 break;
1621 case LY_STMT_REFERENCE:
1622 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
1623 break;
1624 case LY_STMT_PRESENCE:
1625 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
1626 break;
1627 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001628 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001629 break;
1630 default:
1631 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "refine");
1632 return LY_EVALID;
1633 }
1634 }
1635
1636 return LY_SUCCESS;
1637}
1638
1639/**
1640 * @brief Parse the typedef statement.
1641 *
1642 * @param[in] ctx parser context.
1643 * @param[in] stmt Source statement data from the parsed extension instance.
1644 * @param[in] parent Parent node to connect to (not into).
1645 * @param[in,out] typedefs Typedefs to add to.
1646 *
1647 * @return LY_ERR values.
1648 */
1649static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001650lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02001651 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001652{
1653 struct lysp_tpdf *tpdf;
1654
1655 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1656
1657 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
1658
1659 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
1660
1661 /* parse substatements */
1662 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1663 switch (child->kw) {
1664 case LY_STMT_DEFAULT:
1665 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 +01001666 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001667 break;
1668 case LY_STMT_DESCRIPTION:
1669 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
1670 break;
1671 case LY_STMT_REFERENCE:
1672 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
1673 break;
1674 case LY_STMT_STATUS:
1675 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
1676 break;
1677 case LY_STMT_TYPE:
1678 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
1679 break;
1680 case LY_STMT_UNITS:
1681 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
1682 break;
1683 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001684 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001685 break;
1686 default:
1687 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "typedef");
1688 return LY_EVALID;
1689 }
1690 }
1691
1692 /* mandatory substatements */
1693 if (!tpdf->type.name) {
1694 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
1695 return LY_EVALID;
1696 }
1697
1698 /* store data for collision check */
1699 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
1700 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
1701 }
1702
1703 return LY_SUCCESS;
1704}
1705
1706/**
1707 * @brief Parse the input or output statement.
1708 *
1709 * @param[in] ctx parser context.
1710 * @param[in] stmt Source statement data from the parsed extension instance.
1711 * @param[in] parent Parent node to connect to (not into).
1712 * @param[in,out] inout_p Input/output pointer to write to.
1713 *
1714 * @return LY_ERR values.
1715 */
1716static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001717lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001718 struct lysp_node_action_inout *inout_p)
1719{
1720 if (inout_p->nodetype) {
1721 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
1722 return LY_EVALID;
1723 }
1724
1725 /* initiate structure */
1726 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
1727 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
1728 inout_p->parent = parent;
1729
1730 /* parse substatements */
1731 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1732 switch (child->kw) {
1733 case LY_STMT_ANYDATA:
1734 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(stmt->kw));
1735 /* fall through */
1736 case LY_STMT_ANYXML:
1737 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
1738 break;
1739 case LY_STMT_CHOICE:
1740 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
1741 break;
1742 case LY_STMT_CONTAINER:
1743 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
1744 break;
1745 case LY_STMT_LEAF:
1746 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
1747 break;
1748 case LY_STMT_LEAF_LIST:
1749 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
1750 break;
1751 case LY_STMT_LIST:
1752 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
1753 break;
1754 case LY_STMT_USES:
1755 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
1756 break;
1757 case LY_STMT_TYPEDEF:
1758 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
1759 break;
1760 case LY_STMT_MUST:
1761 PARSER_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(stmt->kw));
1762 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
1763 break;
1764 case LY_STMT_GROUPING:
1765 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
1766 break;
1767 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001768 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001769 break;
1770 default:
1771 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
1772 return LY_EVALID;
1773 }
1774 }
1775
1776 if (!inout_p->child) {
1777 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(stmt->kw));
1778 return LY_EVALID;
1779 }
1780
1781 return LY_SUCCESS;
1782}
1783
1784/**
1785 * @brief Parse the action statement.
1786 *
1787 * @param[in] ctx parser context.
1788 * @param[in] stmt Source statement data from the parsed extension instance.
1789 * @param[in] parent Parent node to connect to (not into).
1790 * @param[in,out] actions Actions to add to.
1791 *
1792 * @return LY_ERR values.
1793 */
1794static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001795lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02001796 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001797{
1798 struct lysp_node_action *act;
1799
1800 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1801
1802 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
1803
1804 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
1805 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
1806 act->parent = parent;
1807
1808 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1809 switch (child->kw) {
1810 case LY_STMT_DESCRIPTION:
1811 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
1812 break;
1813 case LY_STMT_IF_FEATURE:
1814 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
1815 break;
1816 case LY_STMT_REFERENCE:
1817 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
1818 break;
1819 case LY_STMT_STATUS:
1820 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
1821 break;
1822
1823 case LY_STMT_INPUT:
1824 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
1825 break;
1826 case LY_STMT_OUTPUT:
1827 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
1828 break;
1829
1830 case LY_STMT_TYPEDEF:
1831 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
1832 break;
1833 case LY_STMT_GROUPING:
1834 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
1835 break;
1836 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001837 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 +01001838 break;
1839 default:
1840 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), parent ? "action" : "rpc");
1841 return LY_EVALID;
1842 }
1843 }
1844
1845 /* always initialize inout, they are technically present (needed for later deviations/refines) */
1846 if (!act->input.nodetype) {
1847 act->input.nodetype = LYS_INPUT;
1848 act->input.parent = &act->node;
1849 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
1850 }
1851 if (!act->output.nodetype) {
1852 act->output.nodetype = LYS_OUTPUT;
1853 act->output.parent = &act->node;
1854 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
1855 }
1856
1857 return LY_SUCCESS;
1858}
1859
1860/**
1861 * @brief Parse the notification statement.
1862 *
1863 * @param[in] ctx parser context.
1864 * @param[in] stmt Source statement data from the parsed extension instance.
1865 * @param[in] parent Parent node to connect to (not into).
1866 * @param[in,out] notifs Notifications to add to.
1867 *
1868 * @return LY_ERR values.
1869 */
1870static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001871lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02001872 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001873{
1874 struct lysp_node_notif *notif;
1875
1876 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1877
1878 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
1879
1880 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
1881 notif->nodetype = LYS_NOTIF;
1882 notif->parent = parent;
1883
1884 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1885 switch (child->kw) {
1886 case LY_STMT_DESCRIPTION:
1887 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
1888 break;
1889 case LY_STMT_IF_FEATURE:
1890 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
1891 break;
1892 case LY_STMT_REFERENCE:
1893 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
1894 break;
1895 case LY_STMT_STATUS:
1896 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
1897 break;
1898
1899 case LY_STMT_ANYDATA:
1900 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
1901 /* fall through */
1902 case LY_STMT_ANYXML:
1903 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
1904 break;
1905 case LY_STMT_CHOICE:
1906 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
1907 break;
1908 case LY_STMT_CONTAINER:
1909 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
1910 break;
1911 case LY_STMT_LEAF:
1912 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
1913 break;
1914 case LY_STMT_LEAF_LIST:
1915 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
1916 break;
1917 case LY_STMT_LIST:
1918 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
1919 break;
1920 case LY_STMT_USES:
1921 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
1922 break;
1923
1924 case LY_STMT_MUST:
1925 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
1926 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
1927 break;
1928 case LY_STMT_TYPEDEF:
1929 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
1930 break;
1931 case LY_STMT_GROUPING:
1932 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
1933 break;
1934 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001935 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001936 break;
1937 default:
1938 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "notification");
1939 return LY_EVALID;
1940 }
1941 }
1942
1943 return LY_SUCCESS;
1944}
1945
1946/**
1947 * @brief Parse the grouping statement.
1948 *
1949 * @param[in] ctx parser context.
1950 * @param[in] stmt Source statement data from the parsed extension instance.
1951 * @param[in] parent Parent node to connect to (not into).
1952 * @param[in,out] groupings Groupings to add to.
1953 *
1954 * @return LY_ERR values.
1955 */
1956static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001957lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02001958 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001959{
1960 struct lysp_node_grp *grp;
1961
1962 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1963
1964 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
1965
1966 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
1967 grp->nodetype = LYS_GROUPING;
1968 grp->parent = parent;
1969
1970 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1971 switch (child->kw) {
1972 case LY_STMT_DESCRIPTION:
1973 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
1974 break;
1975 case LY_STMT_REFERENCE:
1976 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
1977 break;
1978 case LY_STMT_STATUS:
1979 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
1980 break;
1981
1982 case LY_STMT_ANYDATA:
1983 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
1984 /* fall through */
1985 case LY_STMT_ANYXML:
1986 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
1987 break;
1988 case LY_STMT_CHOICE:
1989 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
1990 break;
1991 case LY_STMT_CONTAINER:
1992 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
1993 break;
1994 case LY_STMT_LEAF:
1995 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
1996 break;
1997 case LY_STMT_LEAF_LIST:
1998 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
1999 break;
2000 case LY_STMT_LIST:
2001 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2002 break;
2003 case LY_STMT_USES:
2004 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2005 break;
2006
2007 case LY_STMT_TYPEDEF:
2008 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2009 break;
2010 case LY_STMT_ACTION:
2011 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2012 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2013 break;
2014 case LY_STMT_GROUPING:
2015 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2016 break;
2017 case LY_STMT_NOTIFICATION:
2018 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2019 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2020 break;
2021 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002022 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002023 break;
2024 default:
2025 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "grouping");
2026 return LY_EVALID;
2027 }
2028 }
2029
2030 return LY_SUCCESS;
2031}
2032
2033/**
2034 * @brief Parse the augment statement.
2035 *
2036 * @param[in] ctx parser context.
2037 * @param[in] stmt Source statement data from the parsed extension instance.
2038 * @param[in] parent Parent node to connect to (not into).
2039 * @param[in,out] augments Augments to add to.
2040 *
2041 * @return LY_ERR values.
2042 */
2043static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002044lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002045 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002046{
2047 struct lysp_node_augment *aug;
2048
2049 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2050
2051 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2052
2053 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2054 aug->nodetype = LYS_AUGMENT;
2055 aug->parent = parent;
2056
2057 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2058 switch (child->kw) {
2059 case LY_STMT_DESCRIPTION:
2060 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2061 break;
2062 case LY_STMT_IF_FEATURE:
2063 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2064 break;
2065 case LY_STMT_REFERENCE:
2066 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2067 break;
2068 case LY_STMT_STATUS:
2069 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2070 break;
2071 case LY_STMT_WHEN:
2072 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2073 break;
2074
2075 case LY_STMT_ANYDATA:
2076 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2077 /* fall through */
2078 case LY_STMT_ANYXML:
2079 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2080 break;
2081 case LY_STMT_CASE:
2082 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2083 break;
2084 case LY_STMT_CHOICE:
2085 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2086 break;
2087 case LY_STMT_CONTAINER:
2088 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2089 break;
2090 case LY_STMT_LEAF:
2091 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2092 break;
2093 case LY_STMT_LEAF_LIST:
2094 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2095 break;
2096 case LY_STMT_LIST:
2097 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2098 break;
2099 case LY_STMT_USES:
2100 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2101 break;
2102
2103 case LY_STMT_ACTION:
2104 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2105 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2106 break;
2107 case LY_STMT_NOTIFICATION:
2108 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2109 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2110 break;
2111 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002112 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002113 break;
2114 default:
2115 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "augment");
2116 return LY_EVALID;
2117 }
2118 }
2119
2120 return LY_SUCCESS;
2121}
2122
2123/**
2124 * @brief Parse the uses statement.
2125 *
2126 * @param[in] ctx parser context.
2127 * @param[in] stmt Source statement data from the parsed extension instance.
2128 * @param[in] parent Parent node to connect to (not into).
2129 * @param[in,out] siblings Siblings to add to.
2130 *
2131 * @return LY_ERR values.
2132 */
2133static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002134lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002135 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002136{
2137 struct lysp_node_uses *uses;
2138
2139 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2140
2141 /* create uses structure */
2142 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2143
2144 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2145 uses->nodetype = LYS_USES;
2146 uses->parent = parent;
2147
2148 /* parse substatements */
2149 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2150 switch (child->kw) {
2151 case LY_STMT_DESCRIPTION:
2152 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2153 break;
2154 case LY_STMT_IF_FEATURE:
2155 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2156 break;
2157 case LY_STMT_REFERENCE:
2158 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2159 break;
2160 case LY_STMT_STATUS:
2161 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2162 break;
2163 case LY_STMT_WHEN:
2164 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2165 break;
2166
2167 case LY_STMT_REFINE:
2168 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2169 break;
2170 case LY_STMT_AUGMENT:
2171 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2172 break;
2173 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002174 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002175 break;
2176 default:
2177 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "uses");
2178 return LY_EVALID;
2179 }
2180 }
2181
2182 return LY_SUCCESS;
2183}
2184
2185/**
2186 * @brief Parse the case statement.
2187 *
2188 * @param[in] ctx parser context.
2189 * @param[in] stmt Source statement data from the parsed extension instance.
2190 * @param[in] parent Parent node to connect to (not into).
2191 * @param[in,out] siblings Siblings to add to.
2192 *
2193 * @return LY_ERR values.
2194 */
2195static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002196lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002197 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002198{
2199 struct lysp_node_case *cas;
2200
2201 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2202
2203 /* create new case structure */
2204 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2205
2206 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2207 cas->nodetype = LYS_CASE;
2208 cas->parent = parent;
2209
2210 /* parse substatements */
2211 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2212 switch (child->kw) {
2213 case LY_STMT_DESCRIPTION:
2214 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2215 break;
2216 case LY_STMT_IF_FEATURE:
2217 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2218 break;
2219 case LY_STMT_REFERENCE:
2220 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2221 break;
2222 case LY_STMT_STATUS:
2223 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2224 break;
2225 case LY_STMT_WHEN:
2226 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2227 break;
2228
2229 case LY_STMT_ANYDATA:
2230 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2231 /* fall through */
2232 case LY_STMT_ANYXML:
2233 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2234 break;
2235 case LY_STMT_CHOICE:
2236 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2237 break;
2238 case LY_STMT_CONTAINER:
2239 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2240 break;
2241 case LY_STMT_LEAF:
2242 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2243 break;
2244 case LY_STMT_LEAF_LIST:
2245 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2246 break;
2247 case LY_STMT_LIST:
2248 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2249 break;
2250 case LY_STMT_USES:
2251 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2252 break;
2253 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002254 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002255 break;
2256 default:
2257 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "case");
2258 return LY_EVALID;
2259 }
2260 }
2261 return LY_SUCCESS;
2262}
2263
2264/**
2265 * @brief Parse the choice statement.
2266 *
2267 * @param[in] ctx parser context.
2268 * @param[in] stmt Source statement data from the parsed extension instance.
2269 * @param[in] parent Parent node to connect to (not into).
2270 * @param[in,out] siblings Siblings to add to.
2271 *
2272 * @return LY_ERR values.
2273 */
2274static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002275lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002276 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002277{
2278 struct lysp_node_choice *choice;
2279
2280 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2281
2282 /* create new choice structure */
2283 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2284
2285 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2286 choice->nodetype = LYS_CHOICE;
2287 choice->parent = parent;
2288
2289 /* parse substatements */
2290 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2291 switch (child->kw) {
2292 case LY_STMT_CONFIG:
2293 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2294 break;
2295 case LY_STMT_DESCRIPTION:
2296 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2297 break;
2298 case LY_STMT_IF_FEATURE:
2299 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2300 break;
2301 case LY_STMT_MANDATORY:
2302 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2303 break;
2304 case LY_STMT_REFERENCE:
2305 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2306 break;
2307 case LY_STMT_STATUS:
2308 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2309 break;
2310 case LY_STMT_WHEN:
2311 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2312 break;
2313 case LY_STMT_DEFAULT:
2314 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 +01002315 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002316 break;
2317 case LY_STMT_ANYDATA:
2318 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2319 /* fall through */
2320 case LY_STMT_ANYXML:
2321 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2322 break;
2323 case LY_STMT_CASE:
2324 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2325 break;
2326 case LY_STMT_CHOICE:
2327 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2328 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2329 break;
2330 case LY_STMT_CONTAINER:
2331 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2332 break;
2333 case LY_STMT_LEAF:
2334 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2335 break;
2336 case LY_STMT_LEAF_LIST:
2337 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2338 break;
2339 case LY_STMT_LIST:
2340 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2341 break;
2342 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002343 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002344 break;
2345 default:
2346 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "choice");
2347 return LY_EVALID;
2348 }
2349 }
2350 return LY_SUCCESS;
2351}
2352
2353/**
2354 * @brief Parse the container statement.
2355 *
2356 * @param[in] ctx parser context.
2357 * @param[in] stmt Source statement data from the parsed extension instance.
2358 * @param[in] parent Parent node to connect to (not into).
2359 * @param[in,out] siblings Siblings to add to.
2360 *
2361 * @return LY_ERR values.
2362 */
2363static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002364lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002365 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002366{
2367 struct lysp_node_container *cont;
2368
2369 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2370
2371 /* create new container structure */
2372 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2373
2374 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2375 cont->nodetype = LYS_CONTAINER;
2376 cont->parent = parent;
2377
2378 /* parse substatements */
2379 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2380 switch (child->kw) {
2381 case LY_STMT_CONFIG:
2382 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
2383 break;
2384 case LY_STMT_DESCRIPTION:
2385 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
2386 break;
2387 case LY_STMT_IF_FEATURE:
2388 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
2389 break;
2390 case LY_STMT_REFERENCE:
2391 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
2392 break;
2393 case LY_STMT_STATUS:
2394 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
2395 break;
2396 case LY_STMT_WHEN:
2397 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
2398 break;
2399 case LY_STMT_PRESENCE:
2400 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
2401 break;
2402 case LY_STMT_ANYDATA:
2403 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
2404 /* fall through */
2405 case LY_STMT_ANYXML:
2406 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
2407 break;
2408 case LY_STMT_CHOICE:
2409 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
2410 break;
2411 case LY_STMT_CONTAINER:
2412 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
2413 break;
2414 case LY_STMT_LEAF:
2415 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
2416 break;
2417 case LY_STMT_LEAF_LIST:
2418 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
2419 break;
2420 case LY_STMT_LIST:
2421 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
2422 break;
2423 case LY_STMT_USES:
2424 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
2425 break;
2426
2427 case LY_STMT_TYPEDEF:
2428 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
2429 break;
2430 case LY_STMT_MUST:
2431 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
2432 break;
2433 case LY_STMT_ACTION:
2434 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
2435 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
2436 break;
2437 case LY_STMT_GROUPING:
2438 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
2439 break;
2440 case LY_STMT_NOTIFICATION:
2441 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
2442 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
2443 break;
2444 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002445 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002446 break;
2447 default:
2448 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "container");
2449 return LY_EVALID;
2450 }
2451 }
2452
2453 return LY_SUCCESS;
2454}
2455
2456/**
2457 * @brief Parse the list statement.
2458 *
2459 * @param[in] ctx parser context.
2460 * @param[in] stmt Source statement data from the parsed extension instance.
2461 * @param[in] parent Parent node to connect to (not into).
2462 * @param[in,out] siblings Siblings to add to.
2463 *
2464 * @return LY_ERR values.
2465 */
2466static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002467lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002468 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002469{
2470 struct lysp_node_list *list;
2471
2472 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2473
2474 /* create new list structure */
2475 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
2476
2477 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
2478 list->nodetype = LYS_LIST;
2479 list->parent = parent;
2480
2481 /* parse substatements */
2482 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2483 switch (child->kw) {
2484 case LY_STMT_CONFIG:
2485 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
2486 break;
2487 case LY_STMT_DESCRIPTION:
2488 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
2489 break;
2490 case LY_STMT_IF_FEATURE:
2491 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
2492 break;
2493 case LY_STMT_REFERENCE:
2494 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
2495 break;
2496 case LY_STMT_STATUS:
2497 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
2498 break;
2499 case LY_STMT_WHEN:
2500 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
2501 break;
2502 case LY_STMT_KEY:
2503 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
2504 break;
2505 case LY_STMT_MAX_ELEMENTS:
2506 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
2507 break;
2508 case LY_STMT_MIN_ELEMENTS:
2509 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
2510 break;
2511 case LY_STMT_ORDERED_BY:
2512 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
2513 break;
2514 case LY_STMT_UNIQUE:
2515 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
2516 break;
2517
2518 case LY_STMT_ANYDATA:
2519 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
2520 /* fall through */
2521 case LY_STMT_ANYXML:
2522 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
2523 break;
2524 case LY_STMT_CHOICE:
2525 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
2526 break;
2527 case LY_STMT_CONTAINER:
2528 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
2529 break;
2530 case LY_STMT_LEAF:
2531 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
2532 break;
2533 case LY_STMT_LEAF_LIST:
2534 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
2535 break;
2536 case LY_STMT_LIST:
2537 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
2538 break;
2539 case LY_STMT_USES:
2540 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
2541 break;
2542
2543 case LY_STMT_TYPEDEF:
2544 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
2545 break;
2546 case LY_STMT_MUST:
2547 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
2548 break;
2549 case LY_STMT_ACTION:
2550 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
2551 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
2552 break;
2553 case LY_STMT_GROUPING:
2554 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
2555 break;
2556 case LY_STMT_NOTIFICATION:
2557 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
2558 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
2559 break;
2560 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002561 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002562 break;
2563 default:
2564 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "list");
2565 return LY_EVALID;
2566 }
2567 }
2568
2569 return LY_SUCCESS;
2570}
2571
Radek Krejci335332a2019-09-05 13:03:35 +02002572LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002573lysp_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 +02002574{
Radek Krejciad5963b2019-09-06 16:03:05 +02002575 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002576 uint16_t flags;
Michal Vaskod0625d72022-10-06 15:02:50 +02002577 struct lysp_ctx pctx = {0};
Michal Vasko8a67eff2021-12-07 14:04:47 +01002578 struct ly_set pmods = {0};
2579 void *objs;
Radek Krejci335332a2019-09-05 13:03:35 +02002580
Michal Vasko8a67eff2021-12-07 14:04:47 +01002581 /* local context */
Michal Vaskob36053d2020-03-26 15:49:30 +01002582 pctx.format = LYS_IN_YANG;
Michal Vasko8a67eff2021-12-07 14:04:47 +01002583 pctx.parsed_mods = &pmods;
2584 objs = &ctx->pmod;
2585 pmods.objs = objs;
2586 pmods.count = 1;
Radek Krejci2efc45b2020-12-22 16:25:44 +01002587
Radek Krejciddace2c2021-01-08 11:30:56 +01002588 LOG_LOCSET(NULL, NULL, ctx->path, NULL);
Radek Krejci335332a2019-09-05 13:03:35 +02002589
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002590 switch (stmt->kw) {
2591 case LY_STMT_ACTION:
2592 case LY_STMT_RPC:
2593 ret = lysp_stmt_action(&pctx, stmt, NULL, (struct lysp_node_action **)result);
2594 break;
2595 case LY_STMT_ANYDATA:
2596 case LY_STMT_ANYXML:
2597 ret = lysp_stmt_any(&pctx, stmt, NULL, (struct lysp_node **)result);
2598 break;
2599 case LY_STMT_AUGMENT:
2600 ret = lysp_stmt_augment(&pctx, stmt, NULL, (struct lysp_node_augment **)result);
2601 break;
2602 case LY_STMT_BASE:
2603 ret = lysp_stmt_text_fields(&pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
2604 break;
2605 case LY_STMT_BIT:
2606 case LY_STMT_ENUM:
2607 ret = lysp_stmt_type_enum(&pctx, stmt, (struct lysp_type_enum **)result);
2608 break;
2609 case LY_STMT_CASE:
2610 ret = lysp_stmt_case(&pctx, stmt, NULL, (struct lysp_node **)result);
2611 break;
2612 case LY_STMT_CHOICE:
2613 ret = lysp_stmt_choice(&pctx, stmt, NULL, (struct lysp_node **)result);
2614 break;
2615 case LY_STMT_CONFIG:
Michal Vasko39ed7a22022-02-21 08:34:18 +01002616 assert(*result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002617 ret = lysp_stmt_config(&pctx, stmt, *(uint16_t **)result, exts);
2618 break;
2619 case LY_STMT_CONTACT:
2620 case LY_STMT_DESCRIPTION:
2621 case LY_STMT_ERROR_APP_TAG:
2622 case LY_STMT_ERROR_MESSAGE:
2623 case LY_STMT_KEY:
2624 case LY_STMT_NAMESPACE:
2625 case LY_STMT_ORGANIZATION:
2626 case LY_STMT_PRESENCE:
2627 case LY_STMT_REFERENCE:
2628 case LY_STMT_UNITS:
2629 ret = lysp_stmt_text_field(&pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
2630 break;
2631 case LY_STMT_CONTAINER:
2632 ret = lysp_stmt_container(&pctx, stmt, NULL, (struct lysp_node **)result);
2633 break;
2634 case LY_STMT_DEFAULT:
2635 case LY_STMT_IF_FEATURE:
2636 case LY_STMT_UNIQUE:
2637 ret = lysp_stmt_qnames(&pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
2638 break;
2639 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002640 ret = lysp_stmt_ext(&pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002641 break;
2642 case LY_STMT_FRACTION_DIGITS:
2643 ret = lysp_stmt_type_fracdigits(&pctx, stmt, *(uint8_t **)result, exts);
2644 break;
2645 case LY_STMT_GROUPING:
2646 ret = lysp_stmt_grouping(&pctx, stmt, NULL, (struct lysp_node_grp **)result);
2647 break;
2648 case LY_STMT_INPUT:
2649 case LY_STMT_OUTPUT: {
2650 struct lysp_node_action_inout *inout;
2651
2652 *result = inout = calloc(1, sizeof *inout);
2653 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
2654 ret = lysp_stmt_inout(&pctx, stmt, NULL, inout);
2655 break;
2656 }
2657 case LY_STMT_LEAF:
2658 ret = lysp_stmt_leaf(&pctx, stmt, NULL, (struct lysp_node **)result);
2659 break;
2660 case LY_STMT_LEAF_LIST:
2661 ret = lysp_stmt_leaflist(&pctx, stmt, NULL, (struct lysp_node **)result);
2662 break;
2663 case LY_STMT_LENGTH:
2664 case LY_STMT_MUST:
2665 case LY_STMT_RANGE:
2666 ret = lysp_stmt_restrs(&pctx, stmt, (struct lysp_restr **)result);
2667 break;
2668 case LY_STMT_LIST:
2669 ret = lysp_stmt_list(&pctx, stmt, NULL, (struct lysp_node **)result);
2670 break;
2671 case LY_STMT_MANDATORY:
2672 ret = lysp_stmt_mandatory(&pctx, stmt, *(uint16_t **)result, exts);
2673 break;
2674 case LY_STMT_MAX_ELEMENTS:
2675 flags = 0;
2676 ret = lysp_stmt_maxelements(&pctx, stmt, *(uint32_t **)result, &flags, exts);
2677 break;
2678 case LY_STMT_MIN_ELEMENTS:
2679 flags = 0;
2680 ret = lysp_stmt_minelements(&pctx, stmt, *(uint32_t **)result, &flags, exts);
2681 break;
2682 case LY_STMT_MODIFIER:
2683 ret = lysp_stmt_type_pattern_modifier(&pctx, stmt, (const char **)result, exts);
2684 break;
2685 case LY_STMT_NOTIFICATION:
2686 ret = lysp_stmt_notif(&pctx, stmt, NULL, (struct lysp_node_notif **)result);
2687 break;
2688 case LY_STMT_ORDERED_BY:
2689 ret = lysp_stmt_orderedby(&pctx, stmt, *(uint16_t **)result, exts);
2690 break;
2691 case LY_STMT_PATH: {
2692 const char *str_path = NULL;
2693
2694 LY_CHECK_RET(lysp_stmt_text_field(&pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02002695 ret = ly_path_parse(ctx->ctx, NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002696 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
2697 lydict_remove(ctx->ctx, str_path);
2698 break;
2699 }
2700 case LY_STMT_PATTERN:
2701 ret = lysp_stmt_type_pattern(&pctx, stmt, (struct lysp_restr **)result);
2702 break;
2703 case LY_STMT_POSITION:
2704 case LY_STMT_VALUE:
2705 flags = 0;
2706 ret = lysp_stmt_type_enum_value_pos(&pctx, stmt, *(int64_t **)result, &flags, exts);
2707 break;
2708 case LY_STMT_PREFIX:
2709 ret = lysp_stmt_text_field(&pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
2710 break;
2711 case LY_STMT_REFINE:
2712 ret = lysp_stmt_refine(&pctx, stmt, (struct lysp_refine **)result);
2713 break;
2714 case LY_STMT_REQUIRE_INSTANCE:
2715 flags = 0;
2716 ret = lysp_stmt_type_reqinstance(&pctx, stmt, *(uint8_t **)result, &flags, exts);
2717 break;
Michal Vasko69730152020-10-09 16:30:07 +02002718 case LY_STMT_STATUS:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002719 ret = lysp_stmt_status(&pctx, stmt, *(uint16_t **)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02002720 break;
Radek Krejci335332a2019-09-05 13:03:35 +02002721 case LY_STMT_TYPE: {
2722 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02002723
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002724 *result = type = calloc(1, sizeof *type);
2725 LY_CHECK_ERR_RET(!type, LOGMEM(ctx->ctx), LY_EMEM);
2726 ret = lysp_stmt_type(&pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02002727 break;
Radek Krejci0f969882020-08-21 16:56:47 +02002728 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002729 case LY_STMT_TYPEDEF:
2730 ret = lysp_stmt_typedef(&pctx, stmt, NULL, (struct lysp_tpdf **)result);
2731 break;
2732 case LY_STMT_USES:
2733 ret = lysp_stmt_uses(&pctx, stmt, NULL, (struct lysp_node **)result);
2734 break;
2735 case LY_STMT_WHEN:
2736 ret = lysp_stmt_when(&pctx, stmt, (struct lysp_when **)result);
2737 break;
Radek Krejci335332a2019-09-05 13:03:35 +02002738 default:
2739 LOGINT(ctx->ctx);
2740 return LY_EINT;
2741 }
2742
Radek Krejciddace2c2021-01-08 11:30:56 +01002743 LOG_LOCBACK(0, 0, 1, 0);
Radek Krejciad5963b2019-09-06 16:03:05 +02002744 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02002745}
Michal Vasko59892dd2022-05-13 11:02:30 +02002746
2747void
2748lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
2749{
2750 char path[PATH_MAX];
2751
2752#ifndef __APPLE__
2753 char proc_path[32];
2754 int len;
2755#endif
2756
2757 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
2758 if (*filepath) {
2759 /* filepath already set */
2760 return;
2761 }
2762
2763 switch (in->type) {
2764 case LY_IN_FILEPATH:
2765 if (realpath(in->method.fpath.filepath, path) != NULL) {
2766 lydict_insert(ctx, path, 0, filepath);
2767 } else {
2768 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
2769 }
2770
2771 break;
2772 case LY_IN_FD:
2773#ifdef __APPLE__
2774 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
2775 lydict_insert(ctx, path, 0, filepath);
2776 }
2777#elif defined _WIN32
2778 HANDLE h = _get_osfhandle(in->method.fd);
2779 FILE_NAME_INFO info;
2780 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
2781 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
2782 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
2783 lydict_insert(ctx, buf, len, filepath);
2784 }
2785#else
2786 /* get URI if there is /proc */
2787 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
2788 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
2789 lydict_insert(ctx, path, len, filepath);
2790 }
2791#endif
2792 break;
2793 case LY_IN_MEMORY:
2794 case LY_IN_FILE:
2795 /* nothing to do */
2796 break;
2797 default:
2798 LOGINT(ctx);
2799 break;
2800 }
2801}