blob: 0a035a1ae1ea9ea4109141ca301f99bf0baf935e [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"
Michal Vasko193dacd2022-10-13 08:43:05 +020049#include "schema_features.h"
Radek Krejci77114102021-03-10 15:21:57 +010050#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020051#include "tree.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020052#include "tree_data.h"
53#include "tree_data_internal.h"
Radek Krejci335332a2019-09-05 13:03:35 +020054#include "tree_schema.h"
55#include "tree_schema_internal.h"
56
Michal Vasko59892dd2022-05-13 11:02:30 +020057void
58lyd_ctx_free(struct lyd_ctx *lydctx)
59{
60 ly_set_erase(&lydctx->node_types, NULL);
61 ly_set_erase(&lydctx->meta_types, NULL);
62 ly_set_erase(&lydctx->node_when, NULL);
Michal Vasko135719f2022-08-25 12:18:17 +020063 ly_set_erase(&lydctx->ext_node, free);
Michal Vasko59892dd2022-05-13 11:02:30 +020064 ly_set_erase(&lydctx->ext_val, free);
65}
66
67LY_ERR
68lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op)
69{
70 const struct lyd_node *iter;
71
72 *op = NULL;
73
74 if (!parent) {
75 /* no parent, nothing to look for */
76 return LY_SUCCESS;
77 }
78
79 /* we need to find the operation node if it already exists */
80 for (iter = parent; iter; iter = lyd_parent(iter)) {
81 if (iter->schema && (iter->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
82 break;
83 }
84 }
85
86 if (!iter) {
87 /* no operation found */
88 return LY_SUCCESS;
89 }
90
Michal Vaskoe3ed7dc2022-11-30 11:39:44 +010091 if (!(int_opts & LYD_INTOPT_ANY)) {
92 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
93 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
94 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
95 return LY_EINVAL;
96 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
97 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
98 iter->schema->name);
99 return LY_EINVAL;
100 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
101 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
102 iter->schema->name);
103 return LY_EINVAL;
104 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
105 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
106 iter->schema->name);
107 return LY_EINVAL;
108 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200109 }
110
111 *op = (struct lyd_node *)iter;
112 return LY_SUCCESS;
113}
114
115LY_ERR
116lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
117{
118 LY_ERR rc = LY_SUCCESS;
119
120 LOG_LOCSET(snode, NULL, NULL, NULL);
121
122 if (lydctx->int_opts & LYD_INTOPT_ANY) {
123 /* nothing to check, everything is allowed */
124 goto cleanup;
125 }
126
127 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
128 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
129 rc = LY_EVALID;
130 goto cleanup;
131 }
132
133 if (snode->nodetype == LYS_RPC) {
134 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
135 if (lydctx->op_node) {
136 goto error_node_dup;
137 }
138 } else {
139 goto error_node_inval;
140 }
141 } else if (snode->nodetype == LYS_ACTION) {
142 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
143 if (lydctx->op_node) {
144 goto error_node_dup;
145 }
146 } else {
147 goto error_node_inval;
148 }
149 } else if (snode->nodetype == LYS_NOTIF) {
150 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
151 if (lydctx->op_node) {
152 goto error_node_dup;
153 }
154 } else {
155 goto error_node_inval;
156 }
157 }
158
159 /* success */
160 goto cleanup;
161
162error_node_dup:
163 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
164 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
165 lydctx->op_node->schema->name);
166 rc = LY_EVALID;
167 goto cleanup;
168
169error_node_inval:
170 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
171 snode->name);
172 rc = LY_EVALID;
173
174cleanup:
175 LOG_LOCBACK(1, 0, 0, 0);
176 return rc;
177}
178
179LY_ERR
180lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
181 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
182{
Michal Vasko9dbb91d2023-01-30 13:59:22 +0100183 LY_ERR r;
Michal Vasko59892dd2022-05-13 11:02:30 +0200184 ly_bool incomplete;
185
Michal Vasko9dbb91d2023-01-30 13:59:22 +0100186 if ((r = lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node))) {
187 if (lydctx->data_ctx->ctx != schema->module->ctx) {
188 /* move errors to the main context */
189 ly_err_move(schema->module->ctx, (struct ly_ctx *)lydctx->data_ctx->ctx);
190 }
191 return r;
192 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200193
194 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
195 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
196 }
197 return LY_SUCCESS;
198}
199
200LY_ERR
201lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
202 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
203 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
204{
205 ly_bool incomplete;
206 struct lyd_meta *first = NULL;
207
208 if (meta && *meta) {
209 /* remember the first metadata */
210 first = *meta;
211 }
212
213 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
214 hints, ctx_node, 0, &incomplete));
215
216 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
217 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
218 }
219
220 if (first) {
221 /* always return the first metadata */
222 *meta = first;
223 }
224
225 return LY_SUCCESS;
226}
227
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200228LY_ERR
229lyd_parse_check_keys(struct lyd_node *node)
230{
231 const struct lysc_node *skey = NULL;
232 const struct lyd_node *key;
233
234 assert(node->schema->nodetype == LYS_LIST);
235
236 key = lyd_child(node);
237 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
238 if (!key || (key->schema != skey)) {
239 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
240 return LY_EVALID;
241 }
242
243 key = key->next;
244 }
245
246 return LY_SUCCESS;
247}
248
249LY_ERR
250lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
251 struct lysc_ext_instance *ext)
252{
253 struct lyd_meta *meta2, *prev_meta = NULL;
254 struct lyd_ctx_ext_val *ext_val;
255
Michal Vaskobc9f76f2022-12-01 10:31:38 +0100256 if (lydctx->parse_opts & LYD_PARSE_NO_NEW) {
257 node->flags &= ~LYD_NEW;
258 }
259
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200260 if (lysc_has_when(node->schema)) {
Michal Vaskofbb48c22022-11-30 13:28:03 +0100261 if (lydctx->parse_opts & LYD_PARSE_WHEN_TRUE) {
262 /* the condition was true before */
263 node->flags |= LYD_WHEN_TRUE;
264 }
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200265 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
266 /* remember we need to evaluate this node's when */
267 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
268 }
269 }
270
271 LY_LIST_FOR(*meta, meta2) {
272 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
273 meta2->value.boolean) {
274 /* node is default according to the metadata */
275 node->flags |= LYD_DEFAULT;
276
277 /* delete the metadata */
278 if (prev_meta) {
279 prev_meta->next = meta2->next;
Michal Vasko4754d4a2022-12-01 10:11:21 +0100280 } else if (meta != &node->meta) {
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200281 *meta = (*meta)->next;
282 }
283 lyd_free_meta_single(meta2);
Michal Vasko4754d4a2022-12-01 10:11:21 +0100284
285 /* update dflt flag for all parent NP containers */
286 lyd_cont_set_dflt(lyd_parent(node));
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200287 break;
288 }
289
290 prev_meta = meta2;
291 }
292
293 if (ext) {
294 /* parsed for an extension */
295 node->flags |= LYD_EXT;
296
297 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
298 /* rememeber for validation */
299 ext_val = malloc(sizeof *ext_val);
300 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
301 ext_val->ext = ext;
302 ext_val->sibling = node;
303 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
304 }
305 }
306
307 return LY_SUCCESS;
308}
309
Michal Vasko193dacd2022-10-13 08:43:05 +0200310void
311lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
312{
313 char path[PATH_MAX];
314
315#ifndef __APPLE__
316 char proc_path[32];
317 int len;
318#endif
319
320 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
321 if (*filepath) {
322 /* filepath already set */
323 return;
324 }
325
326 switch (in->type) {
327 case LY_IN_FILEPATH:
328 if (realpath(in->method.fpath.filepath, path) != NULL) {
329 lydict_insert(ctx, path, 0, filepath);
330 } else {
331 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
332 }
333
334 break;
335 case LY_IN_FD:
336#ifdef __APPLE__
337 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
338 lydict_insert(ctx, path, 0, filepath);
339 }
340#elif defined _WIN32
341 HANDLE h = _get_osfhandle(in->method.fd);
342 FILE_NAME_INFO info;
Michal Vasko2bf4af42023-01-04 12:08:38 +0100343
Michal Vasko193dacd2022-10-13 08:43:05 +0200344 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
345 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
Michal Vasko2bf4af42023-01-04 12:08:38 +0100346
Michal Vasko193dacd2022-10-13 08:43:05 +0200347 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
348 lydict_insert(ctx, buf, len, filepath);
349 }
350#else
351 /* get URI if there is /proc */
352 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
353 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
354 lydict_insert(ctx, path, len, filepath);
355 }
356#endif
357 break;
358 case LY_IN_MEMORY:
359 case LY_IN_FILE:
360 /* nothing to do */
361 break;
362 default:
363 LOGINT(ctx);
364 break;
365 }
366}
367
Michal Vaskod0625d72022-10-06 15:02:50 +0200368static 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 +0100369 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200370static 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 +0100371 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200372static 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 +0100373 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200374static 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 +0100375 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200376static 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 +0100377 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200378static 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 +0100379 struct lysp_node **siblings);
380
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100381/**
382 * @brief Validate stmt string value.
383 *
384 * @param[in] ctx Parser context.
385 * @param[in] val_type String value type.
386 * @param[in] val Value to validate.
387 * @return LY_ERR value.
388 */
Radek Krejci335332a2019-09-05 13:03:35 +0200389static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200390lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200391{
Radek Krejci857189e2020-09-01 13:26:36 +0200392 uint8_t prefix = 0;
393 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200394 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200395 size_t utf8_char_len;
396
Michal Vaskocfa1a962023-02-27 09:28:45 +0100397 if (!val) {
398 if (val_type == Y_MAYBE_STR_ARG) {
399 /* fine */
400 return LY_SUCCESS;
401 }
402
403 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Missing an expected string.");
404 return LY_EVALID;
405 }
406
Radek Krejci335332a2019-09-05 13:03:35 +0200407 while (*val) {
408 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200409 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200410
411 switch (val_type) {
412 case Y_IDENTIF_ARG:
413 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
414 break;
415 case Y_PREF_IDENTIF_ARG:
416 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
417 break;
418 case Y_STR_ARG:
419 case Y_MAYBE_STR_ARG:
420 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
421 break;
422 }
423 first = 0;
424 }
425
426 return LY_SUCCESS;
427}
428
429/**
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100430 * @brief Duplicate statement siblings, recursively.
431 *
432 * @param[in] ctx Parser context.
433 * @param[in] stmt Statement to duplicate.
434 * @param[out] first First duplicated statement, the rest follow.
435 * @return LY_ERR value.
436 */
437static LY_ERR
438lysp_stmt_dup(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_stmt **first)
439{
440 struct lysp_stmt *child, *last = NULL;
441
442 LY_LIST_FOR(stmt, stmt) {
443 child = calloc(1, sizeof *child);
444 LY_CHECK_ERR_RET(!child, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
445
446 if (last) {
447 last->next = child;
448 } else {
449 assert(!*first);
450 *first = child;
451 }
452 last = child;
453
454 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &child->stmt));
455 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &child->arg));
456 child->format = stmt->format;
457 LY_CHECK_RET(ly_dup_prefix_data(PARSER_CTX(ctx), stmt->format, stmt->prefix_data, &child->prefix_data));
458 child->flags = stmt->flags;
459 child->kw = stmt->kw;
460
461 /* recursively */
462 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &child->child));
463 }
464
465 return LY_SUCCESS;
466}
467
468/**
Radek Krejci335332a2019-09-05 13:03:35 +0200469 * @brief Parse extension instance.
470 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100471 * @param[in] ctx parser context.
472 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100473 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200474 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
475 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200476 * @return LY_ERR values.
477 */
478static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200479lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200480 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200481{
482 struct lysp_ext_instance *e;
483
Michal Vaskob36053d2020-03-26 15:49:30 +0100484 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200485
486 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200487 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100488 e->parent_stmt = insubstmt;
489 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200490 e->parsed = NULL;
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100491 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &e->child));
Radek Krejci335332a2019-09-05 13:03:35 +0200492
493 /* get optional argument */
494 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200495 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200496 }
497
498 return LY_SUCCESS;
499}
500
501/**
502 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
503 * description, etc...
504 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100505 * @param[in] ctx parser context.
506 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200507 * @param[in] substmt_index Index of this substatement.
508 * @param[in,out] value Place to store the parsed value.
509 * @param[in] arg Type of the YANG keyword argument (of the value).
510 * @param[in,out] exts Extension instances to add to.
511 *
512 * @return LY_ERR values.
513 */
514static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200515lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
516 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200517{
Radek Krejci335332a2019-09-05 13:03:35 +0200518 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200519 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200520 return LY_EVALID;
521 }
522
523 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200524 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200525
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100526 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
527 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200528 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100529 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200530 break;
531 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200532 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200533 return LY_EVALID;
534 }
535 }
536 return LY_SUCCESS;
537}
538
539/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200540 * @brief Parse a qname that can have more instances such as if-feature.
541 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100542 * @param[in] ctx parser context.
543 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200544 * @param[in,out] qnames Parsed qnames to add to.
545 * @param[in] arg Type of the expected argument.
546 * @param[in,out] exts Extension instances to add to.
547 *
548 * @return LY_ERR values.
549 */
550static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200551lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
552 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200553{
554 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200555
556 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
557
558 /* allocate new pointer */
559 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
560 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100561 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200562
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100563 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
564 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200565 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100566 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200567 break;
568 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200569 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200570 return LY_EVALID;
571 }
572 }
573 return LY_SUCCESS;
574}
575
576/**
Radek Krejci335332a2019-09-05 13:03:35 +0200577 * @brief Parse a generic text field that can have more instances such as base.
578 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100579 * @param[in] ctx parser context.
580 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200581 * @param[in,out] texts Parsed values to add to.
582 * @param[in] arg Type of the expected argument.
583 * @param[in,out] exts Extension instances to add to.
584 *
585 * @return LY_ERR values.
586 */
587static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200588lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
589 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200590{
591 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200592
593 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
594
595 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100596 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200597 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200598
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100599 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
600 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200601 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100602 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200603 break;
604 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200605 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200606 return LY_EVALID;
607 }
608 }
609 return LY_SUCCESS;
610}
611
612/**
613 * @brief Parse the status statement.
614 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100615 * @param[in] ctx parser context.
616 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200617 * @param[in,out] flags Flags to add to.
618 * @param[in,out] exts Extension instances to add to.
619 *
620 * @return LY_ERR values.
621 */
622static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200623lysp_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 +0200624{
625 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200626
627 if (*flags & LYS_STATUS_MASK) {
628 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
629 return LY_EVALID;
630 }
631
632 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
633 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100634 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200635 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100636 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200637 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100638 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200639 *flags |= LYS_STATUS_OBSLT;
640 } else {
641 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
642 return LY_EVALID;
643 }
644
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100645 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
646 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200647 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100648 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200649 break;
650 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200651 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200652 return LY_EVALID;
653 }
654 }
655 return LY_SUCCESS;
656}
657
658/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100659 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200660 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100661 * @param[in] ctx parser context.
662 * @param[in] stmt Source statement data from the parsed extension instance.
663 * @param[in,out] when_p When pointer to parse to.
664 *
665 * @return LY_ERR values.
666 */
667static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200668lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100669{
670 LY_ERR ret = LY_SUCCESS;
671 struct lysp_when *when;
672
673 if (*when_p) {
674 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
675 return LY_EVALID;
676 }
677
678 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
679
680 when = calloc(1, sizeof *when);
681 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
682 *when_p = when;
683
684 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
685
686 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
687 switch (child->kw) {
688 case LY_STMT_DESCRIPTION:
689 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
690 break;
691 case LY_STMT_REFERENCE:
692 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
693 break;
694 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100695 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100696 break;
697 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200698 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100699 return LY_EVALID;
700 }
701 }
702 return ret;
703}
704
705/**
706 * @brief Parse the config statement.
707 *
708 * @param[in] ctx parser context.
709 * @param[in] stmt Source statement data from the parsed extension instance.
710 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200711 * @param[in,out] exts Extension instances to add to.
712 *
713 * @return LY_ERR values.
714 */
715static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200716lysp_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 +0200717{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100718 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200719
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100720 if (*flags & LYS_CONFIG_MASK) {
721 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
722 return LY_EVALID;
723 }
724
725 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
726 arg_len = strlen(stmt->arg);
727 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
728 *flags |= LYS_CONFIG_W;
729 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
730 *flags |= LYS_CONFIG_R;
731 } else {
732 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
733 return LY_EVALID;
734 }
735
736 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
737 switch (child->kw) {
738 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100739 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100740 break;
741 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200742 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100743 return LY_EVALID;
744 }
745 }
746
747 return LY_SUCCESS;
748}
749
750/**
751 * @brief Parse the mandatory statement.
752 *
753 * @param[in] ctx parser context.
754 * @param[in] stmt Source statement data from the parsed extension instance.
755 * @param[in,out] flags Flags to add to.
756 * @param[in,out] exts Extension instances to add to.
757 *
758 * @return LY_ERR values.
759 */
760static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200761lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200762 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100763{
764 size_t arg_len;
765
766 if (*flags & LYS_MAND_MASK) {
767 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
768 return LY_EVALID;
769 }
770
771 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
772 arg_len = strlen(stmt->arg);
773 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
774 *flags |= LYS_MAND_TRUE;
775 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
776 *flags |= LYS_MAND_FALSE;
777 } else {
778 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
779 return LY_EVALID;
780 }
781
782 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
783 switch (child->kw) {
784 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100785 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100786 break;
787 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200788 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100789 return LY_EVALID;
790 }
791 }
792
793 return LY_SUCCESS;
794}
795
796/**
797 * @brief Parse a restriction such as range or length.
798 *
799 * @param[in] ctx parser context.
800 * @param[in] stmt Source statement data from the parsed extension instance.
801 * @param[in,out] exts Extension instances to add to.
802 *
803 * @return LY_ERR values.
804 */
805static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200806lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100807{
Radek Krejci335332a2019-09-05 13:03:35 +0200808 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200809 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100810 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200811
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100812 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
813 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200814 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100815 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200816 break;
817 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100818 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200819 break;
820 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100821 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200822 break;
823 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100824 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200825 break;
826 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100827 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200828 break;
829 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200830 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200831 return LY_EVALID;
832 }
833 }
834 return LY_SUCCESS;
835}
836
837/**
838 * @brief Parse a restriction that can have more instances such as must.
839 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100840 * @param[in] ctx parser context.
841 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200842 * @param[in,out] restrs Restrictions to add to.
843 *
844 * @return LY_ERR values.
845 */
846static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200847lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200848{
849 struct lysp_restr *restr;
850
Michal Vaskob36053d2020-03-26 15:49:30 +0100851 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100852 return lysp_stmt_restr(ctx, stmt, restr);
853}
854
855/**
856 * @brief Parse the anydata or anyxml statement.
857 *
858 * @param[in] ctx parser context.
859 * @param[in] stmt Source statement data from the parsed extension instance.
860 * @param[in,out] siblings Siblings to add to.
861 *
862 * @return LY_ERR values.
863 */
864static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200865lysp_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 +0100866{
867 struct lysp_node_anydata *any;
868
869 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
870
871 /* create new structure and insert into siblings */
872 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
873
874 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
875 any->parent = parent;
876
877 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
878
879 /* parse substatements */
880 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
881 switch (child->kw) {
882 case LY_STMT_CONFIG:
883 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
884 break;
885 case LY_STMT_DESCRIPTION:
886 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
887 break;
888 case LY_STMT_IF_FEATURE:
889 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
890 break;
891 case LY_STMT_MANDATORY:
892 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
893 break;
894 case LY_STMT_MUST:
895 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
896 break;
897 case LY_STMT_REFERENCE:
898 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
899 break;
900 case LY_STMT_STATUS:
901 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
902 break;
903 case LY_STMT_WHEN:
904 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
905 break;
906 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100907 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100908 break;
909 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200910 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
911 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? lyplg_ext_stmt2str(LY_STMT_ANYDATA) : lyplg_ext_stmt2str(LY_STMT_ANYXML));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100912 return LY_EVALID;
913 }
914 }
915
916 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200917}
918
919/**
920 * @brief Parse the value or position statement. Substatement of type enum statement.
921 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100922 * @param[in] ctx parser context.
923 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200924 * @param[in,out] value Value to write to.
925 * @param[in,out] flags Flags to write to.
926 * @param[in,out] exts Extension instances to add to.
927 *
928 * @return LY_ERR values.
929 */
930static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200931lysp_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 +0200932 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200933{
934 size_t arg_len;
935 char *ptr = NULL;
Michal Vasko2bf4af42023-01-04 12:08:38 +0100936 long long num = 0;
937 unsigned long long unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200938
939 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200940 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200941 return LY_EVALID;
942 }
943 *flags |= LYS_SET_VALUE;
944
945 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
946
947 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100948 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
949 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200950 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200951 goto error;
952 }
953
954 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100955 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200956 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200957 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200958 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200959 goto error;
960 }
961 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200962 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200963 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200964 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200965 goto error;
966 }
967 }
968 /* we have not parsed the whole argument */
969 if ((size_t)(ptr - stmt->arg) != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200970 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200971 goto error;
972 }
973 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200974 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200975 goto error;
976 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100977 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200978 *value = num;
979 } else {
980 *value = unum;
981 }
982
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100983 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
984 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200985 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100986 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 +0200987 break;
988 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200989 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200990 return LY_EVALID;
991 }
992 }
993 return LY_SUCCESS;
994
995error:
996 return LY_EVALID;
997}
998
999/**
1000 * @brief Parse the enum or bit statement. Substatement of type statement.
1001 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001002 * @param[in] ctx parser context.
1003 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001004 * @param[in,out] enums Enums or bits to add to.
1005 *
1006 * @return LY_ERR values.
1007 */
1008static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001009lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +02001010{
1011 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +02001012
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001013 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 +02001014
Michal Vaskob36053d2020-03-26 15:49:30 +01001015 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001016
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001017 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +02001018 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
1019 } /* else nothing specific for YANG_BIT */
1020
Radek Krejci011e4aa2020-09-04 15:22:31 +02001021 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +02001022 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +02001023
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001024 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1025 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001026 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001027 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001028 break;
1029 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001030 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001031 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001032 break;
1033 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001034 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001035 break;
1036 case LY_STMT_STATUS:
1037 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
1038 break;
1039 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001040 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1041 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001042 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001043 break;
1044 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +02001045 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1046 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001047 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001048 break;
1049 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001050 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001051 break;
1052 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001053 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001054 return LY_EVALID;
1055 }
1056 }
Michal Vasko193dacd2022-10-13 08:43:05 +02001057
Radek Krejci335332a2019-09-05 13:03:35 +02001058 return LY_SUCCESS;
1059}
1060
1061/**
1062 * @brief Parse the fraction-digits statement. Substatement of type statement.
1063 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001064 * @param[in] ctx parser context.
1065 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001066 * @param[in,out] fracdig Value to write to.
1067 * @param[in,out] exts Extension instances to add to.
1068 *
1069 * @return LY_ERR values.
1070 */
1071static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001072lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001073 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001074{
1075 char *ptr;
1076 size_t arg_len;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001077 unsigned long long num;
Radek Krejci335332a2019-09-05 13:03:35 +02001078
1079 if (*fracdig) {
1080 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1081 return LY_EVALID;
1082 }
1083
1084 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1085 arg_len = strlen(stmt->arg);
1086 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1087 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1088 return LY_EVALID;
1089 }
1090
1091 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001092 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001093 /* we have not parsed the whole argument */
1094 if ((size_t)(ptr - stmt->arg) != arg_len) {
1095 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1096 return LY_EVALID;
1097 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001098 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001099 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1100 return LY_EVALID;
1101 }
1102 *fracdig = num;
1103
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001104 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1105 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001106 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001107 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001108 break;
1109 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001110 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001111 return LY_EVALID;
1112 }
1113 }
1114 return LY_SUCCESS;
1115}
1116
1117/**
1118 * @brief Parse the require-instance statement. Substatement of type statement.
1119 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001120 * @param[in] ctx parser context.
1121 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001122 * @param[in,out] reqinst Value to write to.
1123 * @param[in,out] flags Flags to write to.
1124 * @param[in,out] exts Extension instances to add to.
1125 *
1126 * @return LY_ERR values.
1127 */
1128static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001129lysp_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 +02001130 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001131{
1132 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001133
1134 if (*flags & LYS_SET_REQINST) {
1135 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1136 return LY_EVALID;
1137 }
1138 *flags |= LYS_SET_REQINST;
1139
1140 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1141 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001142 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001143 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001144 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001145 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1146 return LY_EVALID;
1147 }
1148
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001149 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1150 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001151 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001152 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001153 break;
1154 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001155 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001156 return LY_EVALID;
1157 }
1158 }
1159 return LY_SUCCESS;
1160}
1161
1162/**
1163 * @brief Parse the modifier statement. Substatement of type pattern statement.
1164 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001165 * @param[in] ctx parser context.
1166 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001167 * @param[in,out] pat Value to write to.
1168 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001169 * @return LY_ERR values.
1170 */
1171static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001172lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001173 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001174{
1175 size_t arg_len;
1176 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001177
Radek Krejcif13b87b2020-12-01 22:02:17 +01001178 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001179 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1180 return LY_EVALID;
1181 }
1182
1183 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1184 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001185 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001186 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1187 return LY_EVALID;
1188 }
1189
1190 /* replace the value in the dictionary */
1191 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001192 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001193 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001194 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001195
Radek Krejcif13b87b2020-12-01 22:02:17 +01001196 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1197 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001198 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001199
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001200 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1201 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001202 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001203 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001204 break;
1205 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001206 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001207 return LY_EVALID;
1208 }
1209 }
1210 return LY_SUCCESS;
1211}
1212
1213/**
1214 * @brief Parse the pattern statement. Substatement of type statement.
1215 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001216 * @param[in] ctx parser context.
1217 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001218 * @param[in,out] patterns Restrictions to add to.
1219 *
1220 * @return LY_ERR values.
1221 */
1222static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001223lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001224{
1225 char *buf;
1226 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001227 struct lysp_restr *restr;
1228
1229 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001230 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001231 arg_len = strlen(stmt->arg);
1232
1233 /* add special meaning first byte */
1234 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001235 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001236 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001237 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001238 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001239 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001240 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001241
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001242 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1243 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001244 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001245 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001246 break;
1247 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001248 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001249 break;
1250 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001251 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001252 break;
1253 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001254 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001255 break;
1256 case LY_STMT_MODIFIER:
1257 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001258 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001259 break;
1260 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001261 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001262 break;
1263 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001264 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001265 return LY_EVALID;
1266 }
1267 }
1268 return LY_SUCCESS;
1269}
1270
1271/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001272 * @brief Parse the deviate statement. Substatement of deviation statement.
1273 *
1274 * @param[in] ctx parser context.
1275 * @param[in] stmt Source statement data from the parsed extension instance.
1276 * @param[in,out] devs Array of deviates to add to.
1277 * @param[in,out] exts Extension instances to add to.
1278 * @return LY_ERR values.
1279 */
1280static LY_ERR
1281lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1282{
1283 (void)stmt;
1284 (void)devs;
1285 (void)exts;
1286
1287 /* TODO */
1288 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1289 return LY_EINVAL;
1290}
1291
1292/**
1293 * @brief Parse the deviation statement.
1294 *
1295 * @param[in] ctx parser context.
1296 * @param[in] stmt Source statement data from the parsed extension instance.
1297 * @param[in,out] deviations Array of deviations to add to.
1298 * @return LY_ERR values.
1299 */
1300static LY_ERR
1301lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1302{
1303 struct lysp_deviation *dev;
1304
1305 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1306
1307 /* store nodeid */
1308 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1309 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1310
1311 /* parse substatements */
1312 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1313 switch (child->kw) {
1314 case LY_STMT_DESCRIPTION:
1315 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1316 break;
1317 case LY_STMT_DEVIATE:
1318 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1319 break;
1320 case LY_STMT_REFERENCE:
1321 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1322 break;
1323 case LY_STMT_EXTENSION_INSTANCE:
1324 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1325 break;
1326 default:
1327 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1328 return LY_EVALID;
1329 }
1330 }
1331
1332 return LY_SUCCESS;
1333}
1334
1335/**
1336 * @brief Parse the yang-version statement.
1337 *
1338 * @param[in] ctx parser context.
1339 * @param[in] stmt Source statement data from the parsed extension instance.
1340 * @param[out] version Version to write to.
1341 * @param[in,out] exts Extension instances to add to.
1342 * @return LY_ERR values.
1343 */
1344static LY_ERR
1345lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1346{
1347 if (*version) {
1348 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1349 return LY_EVALID;
1350 }
1351
1352 /* store flag */
1353 if (!strcmp(stmt->arg, "1")) {
1354 *version = LYS_VERSION_1_0;
1355 } else if (!strcmp(stmt->arg, "1.1")) {
1356 *version = LYS_VERSION_1_1;
1357 } else {
1358 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yang-version");
1359 return LY_EVALID;
1360 }
1361
1362 /* parse substatements */
1363 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1364 switch (child->kw) {
1365 case LY_STMT_EXTENSION_INSTANCE:
1366 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1367 break;
1368 default:
1369 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1370 return LY_EVALID;
1371 }
1372 }
1373
1374 return LY_SUCCESS;
1375}
1376
1377/**
1378 * @brief Parse the module statement.
1379 *
1380 * @param[in] ctx parser context.
1381 * @param[in] stmt Source statement data from the parsed extension instance.
1382 * @param[in,out] mod Module to fill.
1383 * @return LY_ERR values.
1384 */
1385static LY_ERR
1386lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1387{
1388 (void)stmt;
1389 (void)mod;
1390
1391 /* TODO */
1392 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1393 return LY_EINVAL;
1394}
1395
1396/**
1397 * @brief Parse the submodule statement.
1398 *
1399 * @param[in] ctx parser context.
1400 * @param[in] stmt Source statement data from the parsed extension instance.
1401 * @param[in,out] submod Module to fill.
1402 * @return LY_ERR values.
1403 */
1404static LY_ERR
1405lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1406{
1407 (void)stmt;
1408 (void)submod;
1409
1410 /* TODO */
1411 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1412 return LY_EINVAL;
1413}
1414
1415/**
1416 * @brief Parse the yin-element statement. Substatement of argument statement.
1417 *
1418 * @param[in] ctx parser context.
1419 * @param[in] stmt Source statement data from the parsed extension instance.
1420 * @param[in,out] flags Flags to write to.
1421 * @param[in,out] exts Extension instances to add to.
1422 * @return LY_ERR values.
1423 */
1424static LY_ERR
1425lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1426{
1427 if (*flags & LYS_YINELEM_MASK) {
1428 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1429 return LY_EVALID;
1430 }
1431
1432 /* store flag */
1433 if (!strcmp(stmt->arg, "true")) {
1434 *flags |= LYS_YINELEM_TRUE;
1435 } else if (!strcmp(stmt->arg, "false")) {
1436 *flags |= LYS_YINELEM_FALSE;
1437 } else {
1438 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yin-element");
1439 return LY_EVALID;
1440 }
1441
1442 /* parse substatements */
1443 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1444 switch (child->kw) {
1445 case LY_STMT_EXTENSION_INSTANCE:
1446 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1447 break;
1448 default:
1449 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1450 return LY_EVALID;
1451 }
1452 }
1453
1454 return LY_SUCCESS;
1455}
1456
1457/**
1458 * @brief Parse the argument statement. Substatement of extension statement.
1459 *
1460 * @param[in] ctx parser context.
1461 * @param[in] stmt Source statement data from the parsed extension instance.
1462 * @param[in,out] ex Extension to fill.
1463 * @return LY_ERR values.
1464 */
1465static LY_ERR
1466lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1467{
1468 if (ex->argname) {
1469 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1470 return LY_EVALID;
1471 }
1472
1473 /* store argument name */
1474 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1475 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1476
1477 /* parse substatements */
1478 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1479 switch (child->kw) {
1480 case LY_STMT_YIN_ELEMENT:
1481 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1482 break;
1483 case LY_STMT_EXTENSION_INSTANCE:
1484 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1485 break;
1486 default:
1487 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1488 return LY_EVALID;
1489 }
1490 }
1491
1492 return LY_SUCCESS;
1493}
1494
1495/**
1496 * @brief Parse the extension statement.
1497 *
1498 * @param[in] ctx parser context.
1499 * @param[in] stmt Source statement data from the parsed extension instance.
1500 * @param[in,out] extensions Array of extensions to add to.
1501 * @return LY_ERR values.
1502 */
1503static LY_ERR
1504lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1505{
1506 struct lysp_ext *ex;
1507
1508 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1509
1510 /* store name */
1511 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1512 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1513
1514 /* parse substatements */
1515 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1516 switch (child->kw) {
1517 case LY_STMT_DESCRIPTION:
1518 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1519 break;
1520 case LY_STMT_REFERENCE:
1521 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1522 break;
1523 case LY_STMT_STATUS:
1524 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1525 break;
1526 case LY_STMT_ARGUMENT:
1527 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1528 break;
1529 case LY_STMT_EXTENSION_INSTANCE:
1530 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1531 break;
1532 default:
1533 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1534 return LY_EVALID;
1535 }
1536 }
1537
1538 return LY_SUCCESS;
1539}
1540
1541/**
1542 * @brief Parse the feature statement.
1543 *
1544 * @param[in] ctx parser context.
1545 * @param[in] stmt Source statement data from the parsed extension instance.
1546 * @param[in,out] features Array of features to add to.
1547 * @return LY_ERR values.
1548 */
1549static LY_ERR
1550lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1551{
1552 struct lysp_feature *feat;
1553
1554 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1555
1556 /* store name */
1557 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1558 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1559
1560 /* parse substatements */
1561 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1562 switch (child->kw) {
1563 case LY_STMT_DESCRIPTION:
1564 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1565 break;
1566 case LY_STMT_IF_FEATURE:
1567 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1568 break;
1569 case LY_STMT_REFERENCE:
1570 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1571 break;
1572 case LY_STMT_STATUS:
1573 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1574 break;
1575 case LY_STMT_EXTENSION_INSTANCE:
1576 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1577 break;
1578 default:
1579 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1580 return LY_EVALID;
1581 }
1582 }
1583
1584 return LY_SUCCESS;
1585}
1586
1587/**
1588 * @brief Parse the identity statement.
1589 *
1590 * @param[in] ctx parser context.
1591 * @param[in] stmt Source statement data from the parsed extension instance.
1592 * @param[in,out] identities Array of identities to add to.
1593 * @return LY_ERR values.
1594 */
1595static LY_ERR
1596lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1597{
1598 struct lysp_ident *ident;
1599
1600 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1601
1602 /* store name */
1603 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1604 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1605
1606 /* parse substatements */
1607 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1608 switch (child->kw) {
1609 case LY_STMT_DESCRIPTION:
1610 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1611 break;
1612 case LY_STMT_IF_FEATURE:
1613 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1614 break;
1615 case LY_STMT_REFERENCE:
1616 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1617 break;
1618 case LY_STMT_STATUS:
1619 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1620 break;
1621 case LY_STMT_BASE:
1622 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1623 break;
1624 case LY_STMT_EXTENSION_INSTANCE:
1625 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1626 break;
1627 default:
1628 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1629 return LY_EVALID;
1630 }
1631 }
1632
1633 return LY_SUCCESS;
1634}
1635
1636/**
1637 * @brief Parse the import statement.
1638 *
1639 * @param[in] ctx parser context.
1640 * @param[in] stmt Source statement data from the parsed extension instance.
1641 * @param[in,out] imports Array of imports to add to.
1642 * @return LY_ERR values.
1643 */
1644static LY_ERR
1645lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1646{
1647 struct lysp_import *imp;
1648 const char *str = NULL;
1649
1650 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1651
1652 /* store name */
1653 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1654 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1655
1656 /* parse substatements */
1657 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1658 switch (child->kw) {
1659 case LY_STMT_PREFIX:
1660 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1661 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1662 break;
1663 case LY_STMT_DESCRIPTION:
1664 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1665 break;
1666 case LY_STMT_REFERENCE:
1667 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1668 break;
1669 case LY_STMT_REVISION_DATE:
1670 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1671 strcpy(imp->rev, str);
1672 lydict_remove(PARSER_CTX(ctx), str);
1673 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1674 break;
1675 case LY_STMT_EXTENSION_INSTANCE:
1676 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1677 break;
1678 default:
1679 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1680 return LY_EVALID;
1681 }
1682 }
1683
1684 return LY_SUCCESS;
1685}
1686
1687/**
1688 * @brief Parse the include statement.
1689 *
1690 * @param[in] ctx parser context.
1691 * @param[in] stmt Source statement data from the parsed extension instance.
1692 * @param[in,out] includes Array of identities to add to.
1693 * @return LY_ERR values.
1694 */
1695static LY_ERR
1696lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1697{
1698 struct lysp_include *inc;
1699 const char *str = NULL;
1700
1701 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1702
1703 /* store name */
1704 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1705 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1706
1707 /* parse substatements */
1708 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1709 switch (child->kw) {
1710 case LY_STMT_DESCRIPTION:
1711 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1712 break;
1713 case LY_STMT_REFERENCE:
1714 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1715 break;
1716 case LY_STMT_REVISION_DATE:
1717 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1718 strcpy(inc->rev, str);
1719 lydict_remove(PARSER_CTX(ctx), str);
1720 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1721 break;
1722 case LY_STMT_EXTENSION_INSTANCE:
1723 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1724 break;
1725 default:
1726 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1727 return LY_EVALID;
1728 }
1729 }
1730
1731 return LY_SUCCESS;
1732}
1733
1734/**
1735 * @brief Parse the revision statement.
1736 *
1737 * @param[in] ctx parser context.
1738 * @param[in] stmt Source statement data from the parsed extension instance.
1739 * @param[in,out] includes Array of identities to add to.
1740 * @return LY_ERR values.
1741 */
1742static LY_ERR
1743lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1744{
1745 struct lysp_revision *rev;
1746
1747 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1748
1749 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001750 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001751 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001752
1753 /* parse substatements */
1754 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1755 switch (child->kw) {
1756 case LY_STMT_DESCRIPTION:
1757 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1758 break;
1759 case LY_STMT_REFERENCE:
1760 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1761 break;
1762 case LY_STMT_EXTENSION_INSTANCE:
1763 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1764 break;
1765 default:
1766 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1767 return LY_EVALID;
1768 }
1769 }
1770
1771 return LY_SUCCESS;
1772}
1773
1774/**
Radek Krejci335332a2019-09-05 13:03:35 +02001775 * @brief Parse the type statement.
1776 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001777 * @param[in] ctx parser context.
1778 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001779 * @param[in,out] type Type to wrote to.
1780 *
1781 * @return LY_ERR values.
1782 */
1783static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001784lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001785{
1786 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001787 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001788 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001789
1790 if (type->name) {
1791 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1792 return LY_EVALID;
1793 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001794
1795 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001796 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001797 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001798
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001799 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1800 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001801 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001802 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001803 type->flags |= LYS_SET_BASE;
1804 break;
1805 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001806 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001807 type->flags |= LYS_SET_BIT;
1808 break;
1809 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001810 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001811 type->flags |= LYS_SET_ENUM;
1812 break;
1813 case LY_STMT_FRACTION_DIGITS:
1814 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1815 type->flags |= LYS_SET_FRDIGITS;
1816 break;
1817 case LY_STMT_LENGTH:
1818 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001819 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001820 return LY_EVALID;
1821 }
1822 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001823 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001824
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001825 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001826 type->flags |= LYS_SET_LENGTH;
1827 break;
1828 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001829 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001830 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001831 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001832 lydict_remove(PARSER_CTX(ctx), str_path);
1833 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001834 type->flags |= LYS_SET_PATH;
1835 break;
1836 case LY_STMT_PATTERN:
1837 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1838 type->flags |= LYS_SET_PATTERN;
1839 break;
1840 case LY_STMT_RANGE:
1841 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001842 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001843 return LY_EVALID;
1844 }
1845 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001846 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001847
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001848 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001849 type->flags |= LYS_SET_RANGE;
1850 break;
1851 case LY_STMT_REQUIRE_INSTANCE:
1852 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001853 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001854 break;
1855 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001856 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001857 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1858 type->flags |= LYS_SET_TYPE;
1859 break;
1860 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001861 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001862 break;
1863 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001864 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001865 return LY_EVALID;
1866 }
1867 }
1868 return LY_SUCCESS;
1869}
1870
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001871/**
1872 * @brief Parse the leaf statement.
1873 *
1874 * @param[in] ctx parser context.
1875 * @param[in] stmt Source statement data from the parsed extension instance.
1876 * @param[in] parent Parent node to connect to (not into).
1877 * @param[in,out] siblings Siblings to add to.
1878 *
1879 * @return LY_ERR values.
1880 */
1881static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001882lysp_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 +01001883{
1884 struct lysp_node_leaf *leaf;
1885
1886 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1887
1888 /* create new leaf structure */
1889 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1890 leaf->nodetype = LYS_LEAF;
1891 leaf->parent = parent;
1892
1893 /* get name */
1894 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1895
1896 /* parse substatements */
1897 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1898 switch (child->kw) {
1899 case LY_STMT_CONFIG:
1900 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1901 break;
1902 case LY_STMT_DEFAULT:
1903 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 +01001904 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001905 break;
1906 case LY_STMT_DESCRIPTION:
1907 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1908 break;
1909 case LY_STMT_IF_FEATURE:
1910 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1911 break;
1912 case LY_STMT_MANDATORY:
1913 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1914 break;
1915 case LY_STMT_MUST:
1916 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1917 break;
1918 case LY_STMT_REFERENCE:
1919 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1920 break;
1921 case LY_STMT_STATUS:
1922 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1923 break;
1924 case LY_STMT_TYPE:
1925 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1926 break;
1927 case LY_STMT_UNITS:
1928 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1929 break;
1930 case LY_STMT_WHEN:
1931 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1932 break;
1933 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001934 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001935 break;
1936 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001937 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001938 return LY_EVALID;
1939 }
1940 }
1941
1942 /* mandatory substatements */
1943 if (!leaf->type.name) {
1944 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1945 return LY_EVALID;
1946 }
1947
1948 return LY_SUCCESS;
1949}
1950
1951/**
1952 * @brief Parse the max-elements statement.
1953 *
1954 * @param[in] ctx parser context.
1955 * @param[in] stmt Source statement data from the parsed extension instance.
1956 * @param[in,out] max Value to write to.
1957 * @param[in,out] flags Flags to write to.
1958 * @param[in,out] exts Extension instances to add to.
1959 *
1960 * @return LY_ERR values.
1961 */
1962static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001963lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
1964 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001965{
1966 size_t arg_len;
1967 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001968 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001969
1970 if (*flags & LYS_SET_MAX) {
1971 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1972 return LY_EVALID;
1973 }
1974 *flags |= LYS_SET_MAX;
1975
1976 /* get value */
1977 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1978 arg_len = strlen(stmt->arg);
1979
1980 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1981 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1982 return LY_EVALID;
1983 }
1984
1985 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1986 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001987 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001988 /* we have not parsed the whole argument */
1989 if ((size_t)(ptr - stmt->arg) != arg_len) {
1990 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1991 return LY_EVALID;
1992 }
1993 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1994 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1995 return LY_EVALID;
1996 }
1997
1998 *max = num;
1999 } else {
2000 /* unbounded */
2001 *max = 0;
2002 }
2003
2004 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2005 switch (child->kw) {
2006 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002007 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002008 break;
2009 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002010 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002011 return LY_EVALID;
2012 }
2013 }
2014
2015 return LY_SUCCESS;
2016}
2017
2018/**
2019 * @brief Parse the min-elements statement.
2020 *
2021 * @param[in] ctx parser context.
2022 * @param[in] stmt Source statement data from the parsed extension instance.
2023 * @param[in,out] min Value to write to.
2024 * @param[in,out] flags Flags to write to.
2025 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002026 * @return LY_ERR values.
2027 */
2028static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002029lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
2030 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002031{
2032 size_t arg_len;
2033 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002034 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002035
2036 if (*flags & LYS_SET_MIN) {
2037 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
2038 return LY_EVALID;
2039 }
2040 *flags |= LYS_SET_MIN;
2041
2042 /* get value */
2043 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2044 arg_len = strlen(stmt->arg);
2045
2046 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
2047 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2048 return LY_EVALID;
2049 }
2050
2051 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002052 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002053 /* we have not parsed the whole argument */
2054 if ((size_t)(ptr - stmt->arg) != arg_len) {
2055 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2056 return LY_EVALID;
2057 }
2058 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2059 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
2060 return LY_EVALID;
2061 }
2062 *min = num;
2063
2064 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2065 switch (child->kw) {
2066 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002067 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002068 break;
2069 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002070 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002071 return LY_EVALID;
2072 }
2073 }
2074
2075 return LY_SUCCESS;
2076}
2077
2078/**
2079 * @brief Parse the ordered-by statement.
2080 *
2081 * @param[in] ctx parser context.
2082 * @param[in] stmt Source statement data from the parsed extension instance.
2083 * @param[in,out] flags Flags to write to.
2084 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002085 * @return LY_ERR values.
2086 */
2087static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002088lysp_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 +01002089{
2090 size_t arg_len;
2091
2092 if (*flags & LYS_ORDBY_MASK) {
2093 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2094 return LY_EVALID;
2095 }
2096
2097 /* get value */
2098 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2099 arg_len = strlen(stmt->arg);
2100 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2101 *flags |= LYS_MAND_TRUE;
2102 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2103 *flags |= LYS_MAND_FALSE;
2104 } else {
2105 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2106 return LY_EVALID;
2107 }
2108
2109 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2110 switch (child->kw) {
2111 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002112 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002113 break;
2114 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002115 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002116 return LY_EVALID;
2117 }
2118 }
2119
2120 return LY_SUCCESS;
2121}
2122
2123/**
2124 * @brief Parse the leaf-list 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.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002130 * @return LY_ERR values.
2131 */
2132static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002133lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002134 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002135{
2136 struct lysp_node_leaflist *llist;
2137
2138 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2139
2140 /* create new leaf-list structure */
2141 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2142 llist->nodetype = LYS_LEAFLIST;
2143 llist->parent = parent;
2144
2145 /* get name */
2146 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
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_CONFIG:
2152 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2153 break;
2154 case LY_STMT_DEFAULT:
2155 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2156 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2157 break;
2158 case LY_STMT_DESCRIPTION:
2159 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2160 break;
2161 case LY_STMT_IF_FEATURE:
2162 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2163 break;
2164 case LY_STMT_MAX_ELEMENTS:
2165 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2166 break;
2167 case LY_STMT_MIN_ELEMENTS:
2168 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2169 break;
2170 case LY_STMT_MUST:
2171 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2172 break;
2173 case LY_STMT_ORDERED_BY:
2174 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2175 break;
2176 case LY_STMT_REFERENCE:
2177 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2178 break;
2179 case LY_STMT_STATUS:
2180 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2181 break;
2182 case LY_STMT_TYPE:
2183 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2184 break;
2185 case LY_STMT_UNITS:
2186 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2187 break;
2188 case LY_STMT_WHEN:
2189 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2190 break;
2191 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002192 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002193 break;
2194 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002195 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002196 return LY_EVALID;
2197 }
2198 }
2199
2200 /* mandatory substatements */
2201 if (!llist->type.name) {
2202 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2203 return LY_EVALID;
2204 }
2205
2206 return LY_SUCCESS;
2207}
2208
2209/**
2210 * @brief Parse the refine statement.
2211 *
2212 * @param[in] ctx parser context.
2213 * @param[in] stmt Source statement data from the parsed extension instance.
2214 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002215 * @return LY_ERR values.
2216 */
2217static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002218lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002219{
2220 struct lysp_refine *rf;
2221
2222 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2223
2224 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2225
2226 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2227
2228 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2229 switch (child->kw) {
2230 case LY_STMT_CONFIG:
2231 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2232 break;
2233 case LY_STMT_DEFAULT:
2234 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2235 break;
2236 case LY_STMT_DESCRIPTION:
2237 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2238 break;
2239 case LY_STMT_IF_FEATURE:
2240 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2241 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2242 break;
2243 case LY_STMT_MAX_ELEMENTS:
2244 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2245 break;
2246 case LY_STMT_MIN_ELEMENTS:
2247 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2248 break;
2249 case LY_STMT_MUST:
2250 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2251 break;
2252 case LY_STMT_MANDATORY:
2253 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2254 break;
2255 case LY_STMT_REFERENCE:
2256 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2257 break;
2258 case LY_STMT_PRESENCE:
2259 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2260 break;
2261 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002262 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002263 break;
2264 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002265 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002266 return LY_EVALID;
2267 }
2268 }
2269
2270 return LY_SUCCESS;
2271}
2272
2273/**
2274 * @brief Parse the typedef statement.
2275 *
2276 * @param[in] ctx parser context.
2277 * @param[in] stmt Source statement data from the parsed extension instance.
2278 * @param[in] parent Parent node to connect to (not into).
2279 * @param[in,out] typedefs Typedefs to add to.
2280 *
2281 * @return LY_ERR values.
2282 */
2283static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002284lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002285 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002286{
2287 struct lysp_tpdf *tpdf;
2288
2289 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2290
2291 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2292
2293 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2294
2295 /* parse substatements */
2296 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2297 switch (child->kw) {
2298 case LY_STMT_DEFAULT:
2299 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 +01002300 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002301 break;
2302 case LY_STMT_DESCRIPTION:
2303 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2304 break;
2305 case LY_STMT_REFERENCE:
2306 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2307 break;
2308 case LY_STMT_STATUS:
2309 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2310 break;
2311 case LY_STMT_TYPE:
2312 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2313 break;
2314 case LY_STMT_UNITS:
2315 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2316 break;
2317 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002318 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002319 break;
2320 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002321 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002322 return LY_EVALID;
2323 }
2324 }
2325
2326 /* mandatory substatements */
2327 if (!tpdf->type.name) {
2328 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2329 return LY_EVALID;
2330 }
2331
2332 /* store data for collision check */
2333 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2334 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2335 }
2336
2337 return LY_SUCCESS;
2338}
2339
2340/**
2341 * @brief Parse the input or output statement.
2342 *
2343 * @param[in] ctx parser context.
2344 * @param[in] stmt Source statement data from the parsed extension instance.
2345 * @param[in] parent Parent node to connect to (not into).
2346 * @param[in,out] inout_p Input/output pointer to write to.
2347 *
2348 * @return LY_ERR values.
2349 */
2350static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002351lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002352 struct lysp_node_action_inout *inout_p)
2353{
2354 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002355 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002356 return LY_EVALID;
2357 }
2358
2359 /* initiate structure */
2360 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2361 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2362 inout_p->parent = parent;
2363
2364 /* parse substatements */
2365 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2366 switch (child->kw) {
2367 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002368 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002369 /* fall through */
2370 case LY_STMT_ANYXML:
2371 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2372 break;
2373 case LY_STMT_CHOICE:
2374 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2375 break;
2376 case LY_STMT_CONTAINER:
2377 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2378 break;
2379 case LY_STMT_LEAF:
2380 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2381 break;
2382 case LY_STMT_LEAF_LIST:
2383 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2384 break;
2385 case LY_STMT_LIST:
2386 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2387 break;
2388 case LY_STMT_USES:
2389 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2390 break;
2391 case LY_STMT_TYPEDEF:
2392 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2393 break;
2394 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002395 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002396 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2397 break;
2398 case LY_STMT_GROUPING:
2399 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2400 break;
2401 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002402 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002403 break;
2404 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002405 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002406 return LY_EVALID;
2407 }
2408 }
2409
2410 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002411 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002412 return LY_EVALID;
2413 }
2414
2415 return LY_SUCCESS;
2416}
2417
2418/**
2419 * @brief Parse the action statement.
2420 *
2421 * @param[in] ctx parser context.
2422 * @param[in] stmt Source statement data from the parsed extension instance.
2423 * @param[in] parent Parent node to connect to (not into).
2424 * @param[in,out] actions Actions to add to.
2425 *
2426 * @return LY_ERR values.
2427 */
2428static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002429lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002430 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002431{
2432 struct lysp_node_action *act;
2433
2434 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2435
2436 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2437
2438 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2439 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2440 act->parent = parent;
2441
2442 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2443 switch (child->kw) {
2444 case LY_STMT_DESCRIPTION:
2445 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2446 break;
2447 case LY_STMT_IF_FEATURE:
2448 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2449 break;
2450 case LY_STMT_REFERENCE:
2451 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2452 break;
2453 case LY_STMT_STATUS:
2454 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2455 break;
2456
2457 case LY_STMT_INPUT:
2458 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2459 break;
2460 case LY_STMT_OUTPUT:
2461 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2462 break;
2463
2464 case LY_STMT_TYPEDEF:
2465 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2466 break;
2467 case LY_STMT_GROUPING:
2468 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2469 break;
2470 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002471 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 +01002472 break;
2473 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002474 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002475 return LY_EVALID;
2476 }
2477 }
2478
2479 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2480 if (!act->input.nodetype) {
2481 act->input.nodetype = LYS_INPUT;
2482 act->input.parent = &act->node;
2483 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2484 }
2485 if (!act->output.nodetype) {
2486 act->output.nodetype = LYS_OUTPUT;
2487 act->output.parent = &act->node;
2488 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2489 }
2490
2491 return LY_SUCCESS;
2492}
2493
2494/**
2495 * @brief Parse the notification statement.
2496 *
2497 * @param[in] ctx parser context.
2498 * @param[in] stmt Source statement data from the parsed extension instance.
2499 * @param[in] parent Parent node to connect to (not into).
2500 * @param[in,out] notifs Notifications to add to.
2501 *
2502 * @return LY_ERR values.
2503 */
2504static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002505lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002506 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002507{
2508 struct lysp_node_notif *notif;
2509
2510 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2511
2512 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2513
2514 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2515 notif->nodetype = LYS_NOTIF;
2516 notif->parent = parent;
2517
2518 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2519 switch (child->kw) {
2520 case LY_STMT_DESCRIPTION:
2521 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2522 break;
2523 case LY_STMT_IF_FEATURE:
2524 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2525 break;
2526 case LY_STMT_REFERENCE:
2527 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2528 break;
2529 case LY_STMT_STATUS:
2530 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2531 break;
2532
2533 case LY_STMT_ANYDATA:
2534 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2535 /* fall through */
2536 case LY_STMT_ANYXML:
2537 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2538 break;
2539 case LY_STMT_CHOICE:
2540 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2541 break;
2542 case LY_STMT_CONTAINER:
2543 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2544 break;
2545 case LY_STMT_LEAF:
2546 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2547 break;
2548 case LY_STMT_LEAF_LIST:
2549 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2550 break;
2551 case LY_STMT_LIST:
2552 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2553 break;
2554 case LY_STMT_USES:
2555 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2556 break;
2557
2558 case LY_STMT_MUST:
2559 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2560 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2561 break;
2562 case LY_STMT_TYPEDEF:
2563 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2564 break;
2565 case LY_STMT_GROUPING:
2566 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2567 break;
2568 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002569 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002570 break;
2571 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002572 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002573 return LY_EVALID;
2574 }
2575 }
2576
2577 return LY_SUCCESS;
2578}
2579
2580/**
2581 * @brief Parse the grouping statement.
2582 *
2583 * @param[in] ctx parser context.
2584 * @param[in] stmt Source statement data from the parsed extension instance.
2585 * @param[in] parent Parent node to connect to (not into).
2586 * @param[in,out] groupings Groupings to add to.
2587 *
2588 * @return LY_ERR values.
2589 */
2590static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002591lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002592 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002593{
2594 struct lysp_node_grp *grp;
2595
2596 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2597
2598 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2599
2600 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2601 grp->nodetype = LYS_GROUPING;
2602 grp->parent = parent;
2603
2604 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2605 switch (child->kw) {
2606 case LY_STMT_DESCRIPTION:
2607 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2608 break;
2609 case LY_STMT_REFERENCE:
2610 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2611 break;
2612 case LY_STMT_STATUS:
2613 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2614 break;
2615
2616 case LY_STMT_ANYDATA:
2617 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2618 /* fall through */
2619 case LY_STMT_ANYXML:
2620 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2621 break;
2622 case LY_STMT_CHOICE:
2623 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2624 break;
2625 case LY_STMT_CONTAINER:
2626 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2627 break;
2628 case LY_STMT_LEAF:
2629 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2630 break;
2631 case LY_STMT_LEAF_LIST:
2632 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2633 break;
2634 case LY_STMT_LIST:
2635 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2636 break;
2637 case LY_STMT_USES:
2638 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2639 break;
2640
2641 case LY_STMT_TYPEDEF:
2642 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2643 break;
2644 case LY_STMT_ACTION:
2645 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2646 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2647 break;
2648 case LY_STMT_GROUPING:
2649 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2650 break;
2651 case LY_STMT_NOTIFICATION:
2652 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2653 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2654 break;
2655 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002656 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002657 break;
2658 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002659 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002660 return LY_EVALID;
2661 }
2662 }
2663
2664 return LY_SUCCESS;
2665}
2666
2667/**
2668 * @brief Parse the augment statement.
2669 *
2670 * @param[in] ctx parser context.
2671 * @param[in] stmt Source statement data from the parsed extension instance.
2672 * @param[in] parent Parent node to connect to (not into).
2673 * @param[in,out] augments Augments to add to.
2674 *
2675 * @return LY_ERR values.
2676 */
2677static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002678lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002679 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002680{
2681 struct lysp_node_augment *aug;
2682
2683 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2684
2685 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2686
2687 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2688 aug->nodetype = LYS_AUGMENT;
2689 aug->parent = parent;
2690
2691 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2692 switch (child->kw) {
2693 case LY_STMT_DESCRIPTION:
2694 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2695 break;
2696 case LY_STMT_IF_FEATURE:
2697 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2698 break;
2699 case LY_STMT_REFERENCE:
2700 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2701 break;
2702 case LY_STMT_STATUS:
2703 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2704 break;
2705 case LY_STMT_WHEN:
2706 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2707 break;
2708
2709 case LY_STMT_ANYDATA:
2710 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2711 /* fall through */
2712 case LY_STMT_ANYXML:
2713 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2714 break;
2715 case LY_STMT_CASE:
2716 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2717 break;
2718 case LY_STMT_CHOICE:
2719 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2720 break;
2721 case LY_STMT_CONTAINER:
2722 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2723 break;
2724 case LY_STMT_LEAF:
2725 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2726 break;
2727 case LY_STMT_LEAF_LIST:
2728 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2729 break;
2730 case LY_STMT_LIST:
2731 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2732 break;
2733 case LY_STMT_USES:
2734 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2735 break;
2736
2737 case LY_STMT_ACTION:
2738 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2739 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2740 break;
2741 case LY_STMT_NOTIFICATION:
2742 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2743 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2744 break;
2745 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002746 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002747 break;
2748 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002749 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002750 return LY_EVALID;
2751 }
2752 }
2753
2754 return LY_SUCCESS;
2755}
2756
2757/**
2758 * @brief Parse the uses statement.
2759 *
2760 * @param[in] ctx parser context.
2761 * @param[in] stmt Source statement data from the parsed extension instance.
2762 * @param[in] parent Parent node to connect to (not into).
2763 * @param[in,out] siblings Siblings to add to.
2764 *
2765 * @return LY_ERR values.
2766 */
2767static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002768lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002769 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002770{
2771 struct lysp_node_uses *uses;
2772
2773 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2774
2775 /* create uses structure */
2776 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2777
2778 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2779 uses->nodetype = LYS_USES;
2780 uses->parent = parent;
2781
2782 /* parse substatements */
2783 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2784 switch (child->kw) {
2785 case LY_STMT_DESCRIPTION:
2786 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2787 break;
2788 case LY_STMT_IF_FEATURE:
2789 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2790 break;
2791 case LY_STMT_REFERENCE:
2792 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2793 break;
2794 case LY_STMT_STATUS:
2795 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2796 break;
2797 case LY_STMT_WHEN:
2798 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2799 break;
2800
2801 case LY_STMT_REFINE:
2802 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2803 break;
2804 case LY_STMT_AUGMENT:
2805 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2806 break;
2807 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002808 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002809 break;
2810 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002811 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002812 return LY_EVALID;
2813 }
2814 }
2815
2816 return LY_SUCCESS;
2817}
2818
2819/**
2820 * @brief Parse the case statement.
2821 *
2822 * @param[in] ctx parser context.
2823 * @param[in] stmt Source statement data from the parsed extension instance.
2824 * @param[in] parent Parent node to connect to (not into).
2825 * @param[in,out] siblings Siblings to add to.
2826 *
2827 * @return LY_ERR values.
2828 */
2829static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002830lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002831 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002832{
2833 struct lysp_node_case *cas;
2834
2835 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2836
2837 /* create new case structure */
2838 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2839
2840 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2841 cas->nodetype = LYS_CASE;
2842 cas->parent = parent;
2843
2844 /* parse substatements */
2845 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2846 switch (child->kw) {
2847 case LY_STMT_DESCRIPTION:
2848 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2849 break;
2850 case LY_STMT_IF_FEATURE:
2851 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2852 break;
2853 case LY_STMT_REFERENCE:
2854 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2855 break;
2856 case LY_STMT_STATUS:
2857 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2858 break;
2859 case LY_STMT_WHEN:
2860 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2861 break;
2862
2863 case LY_STMT_ANYDATA:
2864 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2865 /* fall through */
2866 case LY_STMT_ANYXML:
2867 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2868 break;
2869 case LY_STMT_CHOICE:
2870 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2871 break;
2872 case LY_STMT_CONTAINER:
2873 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2874 break;
2875 case LY_STMT_LEAF:
2876 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2877 break;
2878 case LY_STMT_LEAF_LIST:
2879 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2880 break;
2881 case LY_STMT_LIST:
2882 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2883 break;
2884 case LY_STMT_USES:
2885 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2886 break;
2887 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002888 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002889 break;
2890 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002891 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002892 return LY_EVALID;
2893 }
2894 }
2895 return LY_SUCCESS;
2896}
2897
2898/**
2899 * @brief Parse the choice statement.
2900 *
2901 * @param[in] ctx parser context.
2902 * @param[in] stmt Source statement data from the parsed extension instance.
2903 * @param[in] parent Parent node to connect to (not into).
2904 * @param[in,out] siblings Siblings to add to.
2905 *
2906 * @return LY_ERR values.
2907 */
2908static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002909lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002910 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002911{
2912 struct lysp_node_choice *choice;
2913
2914 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2915
2916 /* create new choice structure */
2917 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2918
2919 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2920 choice->nodetype = LYS_CHOICE;
2921 choice->parent = parent;
2922
2923 /* parse substatements */
2924 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2925 switch (child->kw) {
2926 case LY_STMT_CONFIG:
2927 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2928 break;
2929 case LY_STMT_DESCRIPTION:
2930 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2931 break;
2932 case LY_STMT_IF_FEATURE:
2933 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2934 break;
2935 case LY_STMT_MANDATORY:
2936 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2937 break;
2938 case LY_STMT_REFERENCE:
2939 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2940 break;
2941 case LY_STMT_STATUS:
2942 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2943 break;
2944 case LY_STMT_WHEN:
2945 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2946 break;
2947 case LY_STMT_DEFAULT:
2948 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 +01002949 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002950 break;
2951 case LY_STMT_ANYDATA:
2952 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2953 /* fall through */
2954 case LY_STMT_ANYXML:
2955 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2956 break;
2957 case LY_STMT_CASE:
2958 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2959 break;
2960 case LY_STMT_CHOICE:
2961 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2962 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2963 break;
2964 case LY_STMT_CONTAINER:
2965 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2966 break;
2967 case LY_STMT_LEAF:
2968 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2969 break;
2970 case LY_STMT_LEAF_LIST:
2971 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2972 break;
2973 case LY_STMT_LIST:
2974 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2975 break;
2976 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002977 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002978 break;
2979 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002980 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002981 return LY_EVALID;
2982 }
2983 }
2984 return LY_SUCCESS;
2985}
2986
2987/**
2988 * @brief Parse the container statement.
2989 *
2990 * @param[in] ctx parser context.
2991 * @param[in] stmt Source statement data from the parsed extension instance.
2992 * @param[in] parent Parent node to connect to (not into).
2993 * @param[in,out] siblings Siblings to add to.
2994 *
2995 * @return LY_ERR values.
2996 */
2997static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002998lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002999 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003000{
3001 struct lysp_node_container *cont;
3002
3003 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3004
3005 /* create new container structure */
3006 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
3007
3008 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
3009 cont->nodetype = LYS_CONTAINER;
3010 cont->parent = parent;
3011
3012 /* parse substatements */
3013 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3014 switch (child->kw) {
3015 case LY_STMT_CONFIG:
3016 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
3017 break;
3018 case LY_STMT_DESCRIPTION:
3019 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
3020 break;
3021 case LY_STMT_IF_FEATURE:
3022 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
3023 break;
3024 case LY_STMT_REFERENCE:
3025 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
3026 break;
3027 case LY_STMT_STATUS:
3028 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
3029 break;
3030 case LY_STMT_WHEN:
3031 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
3032 break;
3033 case LY_STMT_PRESENCE:
3034 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
3035 break;
3036 case LY_STMT_ANYDATA:
3037 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
3038 /* fall through */
3039 case LY_STMT_ANYXML:
3040 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
3041 break;
3042 case LY_STMT_CHOICE:
3043 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
3044 break;
3045 case LY_STMT_CONTAINER:
3046 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
3047 break;
3048 case LY_STMT_LEAF:
3049 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
3050 break;
3051 case LY_STMT_LEAF_LIST:
3052 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
3053 break;
3054 case LY_STMT_LIST:
3055 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
3056 break;
3057 case LY_STMT_USES:
3058 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
3059 break;
3060
3061 case LY_STMT_TYPEDEF:
3062 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
3063 break;
3064 case LY_STMT_MUST:
3065 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
3066 break;
3067 case LY_STMT_ACTION:
3068 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
3069 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
3070 break;
3071 case LY_STMT_GROUPING:
3072 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3073 break;
3074 case LY_STMT_NOTIFICATION:
3075 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3076 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3077 break;
3078 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003079 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003080 break;
3081 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003082 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003083 return LY_EVALID;
3084 }
3085 }
3086
3087 return LY_SUCCESS;
3088}
3089
3090/**
3091 * @brief Parse the list statement.
3092 *
3093 * @param[in] ctx parser context.
3094 * @param[in] stmt Source statement data from the parsed extension instance.
3095 * @param[in] parent Parent node to connect to (not into).
3096 * @param[in,out] siblings Siblings to add to.
3097 *
3098 * @return LY_ERR values.
3099 */
3100static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003101lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003102 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003103{
3104 struct lysp_node_list *list;
3105
3106 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3107
3108 /* create new list structure */
3109 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3110
3111 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3112 list->nodetype = LYS_LIST;
3113 list->parent = parent;
3114
3115 /* parse substatements */
3116 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3117 switch (child->kw) {
3118 case LY_STMT_CONFIG:
3119 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3120 break;
3121 case LY_STMT_DESCRIPTION:
3122 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3123 break;
3124 case LY_STMT_IF_FEATURE:
3125 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3126 break;
3127 case LY_STMT_REFERENCE:
3128 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3129 break;
3130 case LY_STMT_STATUS:
3131 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3132 break;
3133 case LY_STMT_WHEN:
3134 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3135 break;
3136 case LY_STMT_KEY:
3137 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3138 break;
3139 case LY_STMT_MAX_ELEMENTS:
3140 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3141 break;
3142 case LY_STMT_MIN_ELEMENTS:
3143 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3144 break;
3145 case LY_STMT_ORDERED_BY:
3146 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3147 break;
3148 case LY_STMT_UNIQUE:
3149 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3150 break;
3151
3152 case LY_STMT_ANYDATA:
3153 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3154 /* fall through */
3155 case LY_STMT_ANYXML:
3156 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3157 break;
3158 case LY_STMT_CHOICE:
3159 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3160 break;
3161 case LY_STMT_CONTAINER:
3162 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3163 break;
3164 case LY_STMT_LEAF:
3165 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3166 break;
3167 case LY_STMT_LEAF_LIST:
3168 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3169 break;
3170 case LY_STMT_LIST:
3171 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3172 break;
3173 case LY_STMT_USES:
3174 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3175 break;
3176
3177 case LY_STMT_TYPEDEF:
3178 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3179 break;
3180 case LY_STMT_MUST:
3181 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3182 break;
3183 case LY_STMT_ACTION:
3184 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3185 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3186 break;
3187 case LY_STMT_GROUPING:
3188 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3189 break;
3190 case LY_STMT_NOTIFICATION:
3191 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3192 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3193 break;
3194 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003195 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003196 break;
3197 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003198 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003199 return LY_EVALID;
3200 }
3201 }
3202
3203 return LY_SUCCESS;
3204}
3205
Michal Vasko193dacd2022-10-13 08:43:05 +02003206/**
3207 * @brief Parse generic statement structure into a specific parsed-schema structure.
3208 *
3209 * @param[in] pctx Parse context of the @p stmt being processed.
3210 * @param[in] stmt Generic statement structure to process.
3211 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3212 * @param[in,out] exts [sized array](@ref sizedarrays) For extension instances in case of statements that do not store extension instances in their own list.
3213 * @return LY_ERR value.
3214 */
3215static LY_ERR
3216lysp_stmt_parse(struct lysp_ctx *pctx, const struct lysp_stmt *stmt, void **result, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02003217{
Radek Krejciad5963b2019-09-06 16:03:05 +02003218 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003219 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003220
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003221 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003222 case LY_STMT_NOTIFICATION:
3223 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3224 break;
3225 case LY_STMT_INPUT:
3226 case LY_STMT_OUTPUT: {
3227 struct lysp_node_action_inout *inout;
3228
3229 *result = inout = calloc(1, sizeof *inout);
3230 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3231 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3232 break;
3233 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003234 case LY_STMT_ACTION:
3235 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003236 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003237 break;
3238 case LY_STMT_ANYDATA:
3239 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003240 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003241 break;
3242 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003243 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003244 break;
3245 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003246 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003247 break;
3248 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003249 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003250 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003251 case LY_STMT_CONTAINER:
3252 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003253 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003254 case LY_STMT_GROUPING:
3255 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3256 break;
3257 case LY_STMT_LEAF:
3258 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3259 break;
3260 case LY_STMT_LEAF_LIST:
3261 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3262 break;
3263 case LY_STMT_LIST:
3264 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3265 break;
3266 case LY_STMT_USES:
3267 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3268 break;
3269 case LY_STMT_BASE:
3270 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3271 break;
3272 case LY_STMT_ARGUMENT:
3273 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003274 case LY_STMT_CONTACT:
3275 case LY_STMT_DESCRIPTION:
3276 case LY_STMT_ERROR_APP_TAG:
3277 case LY_STMT_ERROR_MESSAGE:
3278 case LY_STMT_KEY:
3279 case LY_STMT_NAMESPACE:
3280 case LY_STMT_ORGANIZATION:
3281 case LY_STMT_PRESENCE:
3282 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003283 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003284 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003285 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003286 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003287 case LY_STMT_BIT:
3288 case LY_STMT_ENUM:
3289 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3290 break;
3291 case LY_STMT_CONFIG:
3292 assert(*result);
3293 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003294 break;
3295 case LY_STMT_DEFAULT:
3296 case LY_STMT_IF_FEATURE:
3297 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003298 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3299 break;
3300 case LY_STMT_DEVIATE:
3301 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3302 break;
3303 case LY_STMT_DEVIATION:
3304 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3305 break;
3306 case LY_STMT_EXTENSION:
3307 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003308 break;
3309 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003310 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3311 break;
3312 case LY_STMT_FEATURE:
3313 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003314 break;
3315 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003316 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003317 break;
3318 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003319 case LY_STMT_RANGE: {
3320 struct lysp_restr *restr;
3321
3322 *result = restr = calloc(1, sizeof *restr);
3323 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3324
3325 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003326 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003327 }
3328 case LY_STMT_MUST:
3329 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3330 break;
3331 case LY_STMT_IDENTITY:
3332 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3333 break;
3334 case LY_STMT_IMPORT:
3335 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3336 break;
3337 case LY_STMT_INCLUDE:
3338 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003339 break;
3340 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003341 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003342 break;
3343 case LY_STMT_MAX_ELEMENTS:
3344 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003345 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003346 break;
3347 case LY_STMT_MIN_ELEMENTS:
3348 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003349 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003350 break;
3351 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003352 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003353 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003354 case LY_STMT_MODULE: {
3355 struct lysp_module *mod;
3356
3357 *result = mod = calloc(1, sizeof *mod);
3358 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3359 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003360 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003361 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003362 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003363 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003364 break;
3365 case LY_STMT_PATH: {
3366 const char *str_path = NULL;
3367
Michal Vasko193dacd2022-10-13 08:43:05 +02003368 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3369 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003370 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003371 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003372 break;
3373 }
3374 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003375 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003376 break;
3377 case LY_STMT_POSITION:
3378 case LY_STMT_VALUE:
3379 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003380 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003381 break;
3382 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003383 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003384 break;
3385 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003386 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003387 break;
3388 case LY_STMT_REQUIRE_INSTANCE:
3389 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003390 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3391 break;
3392 case LY_STMT_REVISION:
3393 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003394 break;
Michal Vasko69730152020-10-09 16:30:07 +02003395 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003396 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003397 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003398 case LY_STMT_SUBMODULE: {
3399 struct lysp_submodule *submod;
3400
3401 *result = submod = calloc(1, sizeof *submod);
3402 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3403 ret = lysp_stmt_submodule(pctx, stmt, submod);
3404 break;
3405 }
Radek Krejci335332a2019-09-05 13:03:35 +02003406 case LY_STMT_TYPE: {
3407 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003408
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003409 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003410 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3411 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003412 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003413 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003414 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003415 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003416 break;
3417 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003418 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3419 break;
3420 case LY_STMT_YANG_VERSION:
3421 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3422 break;
3423 case LY_STMT_YIN_ELEMENT:
3424 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003425 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003426 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003427 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003428 return LY_EINT;
3429 }
3430
Radek Krejciad5963b2019-09-06 16:03:05 +02003431 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003432}
Michal Vasko59892dd2022-05-13 11:02:30 +02003433
Michal Vasko193dacd2022-10-13 08:43:05 +02003434LY_ERR
3435lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003436{
Michal Vasko193dacd2022-10-13 08:43:05 +02003437 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003438
Michal Vasko193dacd2022-10-13 08:43:05 +02003439 if (!substmt->storage) {
3440 /* nothing to parse, ignored */
3441 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003442 }
3443
Michal Vasko193dacd2022-10-13 08:43:05 +02003444 switch (stmt->kw) {
3445 case LY_STMT_NOTIFICATION:
3446 case LY_STMT_INPUT:
3447 case LY_STMT_OUTPUT:
3448 case LY_STMT_ACTION:
3449 case LY_STMT_RPC:
3450 case LY_STMT_ANYDATA:
3451 case LY_STMT_ANYXML:
3452 case LY_STMT_AUGMENT:
3453 case LY_STMT_CASE:
3454 case LY_STMT_CHOICE:
3455 case LY_STMT_CONTAINER:
3456 case LY_STMT_GROUPING:
3457 case LY_STMT_LEAF:
3458 case LY_STMT_LEAF_LIST:
3459 case LY_STMT_LIST:
3460 case LY_STMT_USES: {
3461 struct lysp_node **pnodes_p, *pnode = NULL;
3462
3463 /* parse the node */
3464 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3465
3466 /* usually is a linked-list of all the parsed schema nodes */
3467 pnodes_p = substmt->storage;
3468 while (*pnodes_p) {
3469 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003470 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003471 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003472
3473 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003474 }
3475 case LY_STMT_BASE:
3476 case LY_STMT_BIT:
3477 case LY_STMT_DEFAULT:
3478 case LY_STMT_DEVIATE:
3479 case LY_STMT_DEVIATION:
3480 case LY_STMT_ENUM:
3481 case LY_STMT_EXTENSION:
3482 case LY_STMT_EXTENSION_INSTANCE:
3483 case LY_STMT_FEATURE:
3484 case LY_STMT_IDENTITY:
3485 case LY_STMT_IF_FEATURE:
3486 case LY_STMT_IMPORT:
3487 case LY_STMT_INCLUDE:
3488 case LY_STMT_MUST:
3489 case LY_STMT_PATTERN:
3490 case LY_STMT_REFINE:
3491 case LY_STMT_REVISION:
3492 case LY_STMT_TYPEDEF:
3493 case LY_STMT_UNIQUE:
3494 /* parse, sized array */
3495 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003496 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003497
3498 case LY_STMT_ARGUMENT:
3499 case LY_STMT_BELONGS_TO:
3500 case LY_STMT_CONTACT:
3501 case LY_STMT_DESCRIPTION:
3502 case LY_STMT_ERROR_APP_TAG:
3503 case LY_STMT_ERROR_MESSAGE:
3504 case LY_STMT_FRACTION_DIGITS:
3505 case LY_STMT_KEY:
3506 case LY_STMT_LENGTH:
3507 case LY_STMT_MANDATORY:
3508 case LY_STMT_MAX_ELEMENTS:
3509 case LY_STMT_MIN_ELEMENTS:
3510 case LY_STMT_MODIFIER:
3511 case LY_STMT_MODULE:
3512 case LY_STMT_NAMESPACE:
3513 case LY_STMT_ORGANIZATION:
3514 case LY_STMT_PATH:
3515 case LY_STMT_POSITION:
3516 case LY_STMT_PREFIX:
3517 case LY_STMT_PRESENCE:
3518 case LY_STMT_RANGE:
3519 case LY_STMT_REFERENCE:
3520 case LY_STMT_REQUIRE_INSTANCE:
3521 case LY_STMT_REVISION_DATE:
3522 case LY_STMT_SUBMODULE:
3523 case LY_STMT_TYPE:
3524 case LY_STMT_UNITS:
3525 case LY_STMT_VALUE:
3526 case LY_STMT_WHEN:
3527 case LY_STMT_YANG_VERSION:
3528 case LY_STMT_YIN_ELEMENT:
3529 /* single item */
3530 if (*(void **)substmt->storage) {
3531 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3532 rc = LY_EVALID;
3533 goto cleanup;
3534 }
3535
3536 /* parse */
3537 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003538 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003539
3540 case LY_STMT_CONFIG:
3541 /* single item */
3542 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3543 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3544 rc = LY_EVALID;
3545 goto cleanup;
3546 }
3547
3548 /* parse */
3549 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3550 break;
3551
3552 case LY_STMT_ORDERED_BY:
3553 /* single item */
3554 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3555 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3556 rc = LY_EVALID;
3557 goto cleanup;
3558 }
3559
3560 /* parse */
3561 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3562 break;
3563
3564 case LY_STMT_STATUS:
3565 /* single item */
3566 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3567 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3568 rc = LY_EVALID;
3569 goto cleanup;
3570 }
3571
3572 /* parse */
3573 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3574 break;
3575
Michal Vasko59892dd2022-05-13 11:02:30 +02003576 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003577 LOGINT(PARSER_CTX(pctx));
3578 rc = LY_EINT;
3579 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003580 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003581
3582cleanup:
3583 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003584}