blob: 7d8131066ec9c1f68b04157b53a748110bbe1f99 [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
397 while (*val) {
398 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200399 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200400
401 switch (val_type) {
402 case Y_IDENTIF_ARG:
403 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
404 break;
405 case Y_PREF_IDENTIF_ARG:
406 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
407 break;
408 case Y_STR_ARG:
409 case Y_MAYBE_STR_ARG:
410 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
411 break;
412 }
413 first = 0;
414 }
415
416 return LY_SUCCESS;
417}
418
419/**
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100420 * @brief Duplicate statement siblings, recursively.
421 *
422 * @param[in] ctx Parser context.
423 * @param[in] stmt Statement to duplicate.
424 * @param[out] first First duplicated statement, the rest follow.
425 * @return LY_ERR value.
426 */
427static LY_ERR
428lysp_stmt_dup(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_stmt **first)
429{
430 struct lysp_stmt *child, *last = NULL;
431
432 LY_LIST_FOR(stmt, stmt) {
433 child = calloc(1, sizeof *child);
434 LY_CHECK_ERR_RET(!child, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
435
436 if (last) {
437 last->next = child;
438 } else {
439 assert(!*first);
440 *first = child;
441 }
442 last = child;
443
444 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &child->stmt));
445 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &child->arg));
446 child->format = stmt->format;
447 LY_CHECK_RET(ly_dup_prefix_data(PARSER_CTX(ctx), stmt->format, stmt->prefix_data, &child->prefix_data));
448 child->flags = stmt->flags;
449 child->kw = stmt->kw;
450
451 /* recursively */
452 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &child->child));
453 }
454
455 return LY_SUCCESS;
456}
457
458/**
Radek Krejci335332a2019-09-05 13:03:35 +0200459 * @brief Parse extension instance.
460 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100461 * @param[in] ctx parser context.
462 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100463 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200464 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
465 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200466 * @return LY_ERR values.
467 */
468static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200469lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200470 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200471{
472 struct lysp_ext_instance *e;
473
Michal Vaskob36053d2020-03-26 15:49:30 +0100474 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200475
476 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200477 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100478 e->parent_stmt = insubstmt;
479 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200480 e->parsed = NULL;
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100481 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &e->child));
Radek Krejci335332a2019-09-05 13:03:35 +0200482
483 /* get optional argument */
484 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200485 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200486 }
487
488 return LY_SUCCESS;
489}
490
491/**
492 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
493 * description, etc...
494 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100495 * @param[in] ctx parser context.
496 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200497 * @param[in] substmt_index Index of this substatement.
498 * @param[in,out] value Place to store the parsed value.
499 * @param[in] arg Type of the YANG keyword argument (of the value).
500 * @param[in,out] exts Extension instances to add to.
501 *
502 * @return LY_ERR values.
503 */
504static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200505lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
506 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200507{
Radek Krejci335332a2019-09-05 13:03:35 +0200508 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200509 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200510 return LY_EVALID;
511 }
512
513 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200514 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200515
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100516 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
517 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200518 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100519 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200520 break;
521 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200522 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200523 return LY_EVALID;
524 }
525 }
526 return LY_SUCCESS;
527}
528
529/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200530 * @brief Parse a qname that can have more instances such as if-feature.
531 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100532 * @param[in] ctx parser context.
533 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200534 * @param[in,out] qnames Parsed qnames to add to.
535 * @param[in] arg Type of the expected argument.
536 * @param[in,out] exts Extension instances to add to.
537 *
538 * @return LY_ERR values.
539 */
540static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200541lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
542 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200543{
544 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200545
546 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
547
548 /* allocate new pointer */
549 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
550 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100551 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200552
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100553 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
554 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200555 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100556 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200557 break;
558 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200559 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200560 return LY_EVALID;
561 }
562 }
563 return LY_SUCCESS;
564}
565
566/**
Radek Krejci335332a2019-09-05 13:03:35 +0200567 * @brief Parse a generic text field that can have more instances such as base.
568 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100569 * @param[in] ctx parser context.
570 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200571 * @param[in,out] texts Parsed values to add to.
572 * @param[in] arg Type of the expected argument.
573 * @param[in,out] exts Extension instances to add to.
574 *
575 * @return LY_ERR values.
576 */
577static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200578lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
579 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200580{
581 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200582
583 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
584
585 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100586 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200587 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200588
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100589 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
590 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200591 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100592 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200593 break;
594 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200595 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200596 return LY_EVALID;
597 }
598 }
599 return LY_SUCCESS;
600}
601
602/**
603 * @brief Parse the status statement.
604 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100605 * @param[in] ctx parser context.
606 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200607 * @param[in,out] flags Flags to add to.
608 * @param[in,out] exts Extension instances to add to.
609 *
610 * @return LY_ERR values.
611 */
612static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200613lysp_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 +0200614{
615 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200616
617 if (*flags & LYS_STATUS_MASK) {
618 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
619 return LY_EVALID;
620 }
621
622 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
623 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100624 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200625 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100626 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200627 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100628 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200629 *flags |= LYS_STATUS_OBSLT;
630 } else {
631 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
632 return LY_EVALID;
633 }
634
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100635 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
636 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200637 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100638 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200639 break;
640 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200641 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200642 return LY_EVALID;
643 }
644 }
645 return LY_SUCCESS;
646}
647
648/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100649 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200650 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100651 * @param[in] ctx parser context.
652 * @param[in] stmt Source statement data from the parsed extension instance.
653 * @param[in,out] when_p When pointer to parse to.
654 *
655 * @return LY_ERR values.
656 */
657static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200658lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100659{
660 LY_ERR ret = LY_SUCCESS;
661 struct lysp_when *when;
662
663 if (*when_p) {
664 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
665 return LY_EVALID;
666 }
667
668 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
669
670 when = calloc(1, sizeof *when);
671 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
672 *when_p = when;
673
674 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
675
676 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
677 switch (child->kw) {
678 case LY_STMT_DESCRIPTION:
679 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
680 break;
681 case LY_STMT_REFERENCE:
682 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
683 break;
684 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100685 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100686 break;
687 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200688 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100689 return LY_EVALID;
690 }
691 }
692 return ret;
693}
694
695/**
696 * @brief Parse the config statement.
697 *
698 * @param[in] ctx parser context.
699 * @param[in] stmt Source statement data from the parsed extension instance.
700 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200701 * @param[in,out] exts Extension instances to add to.
702 *
703 * @return LY_ERR values.
704 */
705static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200706lysp_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 +0200707{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100708 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200709
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100710 if (*flags & LYS_CONFIG_MASK) {
711 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
712 return LY_EVALID;
713 }
714
715 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
716 arg_len = strlen(stmt->arg);
717 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
718 *flags |= LYS_CONFIG_W;
719 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
720 *flags |= LYS_CONFIG_R;
721 } else {
722 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
723 return LY_EVALID;
724 }
725
726 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
727 switch (child->kw) {
728 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100729 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100730 break;
731 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200732 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100733 return LY_EVALID;
734 }
735 }
736
737 return LY_SUCCESS;
738}
739
740/**
741 * @brief Parse the mandatory statement.
742 *
743 * @param[in] ctx parser context.
744 * @param[in] stmt Source statement data from the parsed extension instance.
745 * @param[in,out] flags Flags to add to.
746 * @param[in,out] exts Extension instances to add to.
747 *
748 * @return LY_ERR values.
749 */
750static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200751lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200752 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100753{
754 size_t arg_len;
755
756 if (*flags & LYS_MAND_MASK) {
757 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
758 return LY_EVALID;
759 }
760
761 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
762 arg_len = strlen(stmt->arg);
763 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
764 *flags |= LYS_MAND_TRUE;
765 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
766 *flags |= LYS_MAND_FALSE;
767 } else {
768 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
769 return LY_EVALID;
770 }
771
772 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
773 switch (child->kw) {
774 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100775 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100776 break;
777 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200778 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100779 return LY_EVALID;
780 }
781 }
782
783 return LY_SUCCESS;
784}
785
786/**
787 * @brief Parse a restriction such as range or length.
788 *
789 * @param[in] ctx parser context.
790 * @param[in] stmt Source statement data from the parsed extension instance.
791 * @param[in,out] exts Extension instances to add to.
792 *
793 * @return LY_ERR values.
794 */
795static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200796lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100797{
Radek Krejci335332a2019-09-05 13:03:35 +0200798 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200799 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100800 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200801
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100802 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
803 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200804 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100805 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200806 break;
807 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100808 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200809 break;
810 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100811 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200812 break;
813 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100814 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200815 break;
816 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100817 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200818 break;
819 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200820 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200821 return LY_EVALID;
822 }
823 }
824 return LY_SUCCESS;
825}
826
827/**
828 * @brief Parse a restriction that can have more instances such as must.
829 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100830 * @param[in] ctx parser context.
831 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200832 * @param[in,out] restrs Restrictions to add to.
833 *
834 * @return LY_ERR values.
835 */
836static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200837lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200838{
839 struct lysp_restr *restr;
840
Michal Vaskob36053d2020-03-26 15:49:30 +0100841 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100842 return lysp_stmt_restr(ctx, stmt, restr);
843}
844
845/**
846 * @brief Parse the anydata or anyxml statement.
847 *
848 * @param[in] ctx parser context.
849 * @param[in] stmt Source statement data from the parsed extension instance.
850 * @param[in,out] siblings Siblings to add to.
851 *
852 * @return LY_ERR values.
853 */
854static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200855lysp_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 +0100856{
857 struct lysp_node_anydata *any;
858
859 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
860
861 /* create new structure and insert into siblings */
862 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
863
864 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
865 any->parent = parent;
866
867 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
868
869 /* parse substatements */
870 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
871 switch (child->kw) {
872 case LY_STMT_CONFIG:
873 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
874 break;
875 case LY_STMT_DESCRIPTION:
876 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
877 break;
878 case LY_STMT_IF_FEATURE:
879 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
880 break;
881 case LY_STMT_MANDATORY:
882 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
883 break;
884 case LY_STMT_MUST:
885 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
886 break;
887 case LY_STMT_REFERENCE:
888 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
889 break;
890 case LY_STMT_STATUS:
891 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
892 break;
893 case LY_STMT_WHEN:
894 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
895 break;
896 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100897 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100898 break;
899 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200900 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
901 (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 +0100902 return LY_EVALID;
903 }
904 }
905
906 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200907}
908
909/**
910 * @brief Parse the value or position statement. Substatement of type enum statement.
911 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100912 * @param[in] ctx parser context.
913 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200914 * @param[in,out] value Value to write to.
915 * @param[in,out] flags Flags to write to.
916 * @param[in,out] exts Extension instances to add to.
917 *
918 * @return LY_ERR values.
919 */
920static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200921lysp_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 +0200922 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200923{
924 size_t arg_len;
925 char *ptr = NULL;
Michal Vasko2bf4af42023-01-04 12:08:38 +0100926 long long num = 0;
927 unsigned long long unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200928
929 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200930 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200931 return LY_EVALID;
932 }
933 *flags |= LYS_SET_VALUE;
934
935 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
936
937 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100938 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
939 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200940 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200941 goto error;
942 }
943
944 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100945 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200946 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200947 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200948 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200949 goto error;
950 }
951 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200952 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200953 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200954 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200955 goto error;
956 }
957 }
958 /* we have not parsed the whole argument */
959 if ((size_t)(ptr - stmt->arg) != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200960 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200961 goto error;
962 }
963 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200964 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200965 goto error;
966 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100967 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200968 *value = num;
969 } else {
970 *value = unum;
971 }
972
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100973 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
974 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200975 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100976 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 +0200977 break;
978 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200979 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200980 return LY_EVALID;
981 }
982 }
983 return LY_SUCCESS;
984
985error:
986 return LY_EVALID;
987}
988
989/**
990 * @brief Parse the enum or bit statement. Substatement of type statement.
991 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100992 * @param[in] ctx parser context.
993 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200994 * @param[in,out] enums Enums or bits to add to.
995 *
996 * @return LY_ERR values.
997 */
998static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200999lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +02001000{
1001 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +02001002
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001003 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 +02001004
Michal Vaskob36053d2020-03-26 15:49:30 +01001005 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001006
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001007 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +02001008 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
1009 } /* else nothing specific for YANG_BIT */
1010
Radek Krejci011e4aa2020-09-04 15:22:31 +02001011 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +02001012 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +02001013
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001014 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1015 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001016 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001017 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001018 break;
1019 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001020 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001021 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001022 break;
1023 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001024 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001025 break;
1026 case LY_STMT_STATUS:
1027 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
1028 break;
1029 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001030 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1031 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001032 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001033 break;
1034 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +02001035 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1036 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001037 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001038 break;
1039 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001040 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001041 break;
1042 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001043 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001044 return LY_EVALID;
1045 }
1046 }
Michal Vasko193dacd2022-10-13 08:43:05 +02001047
Radek Krejci335332a2019-09-05 13:03:35 +02001048 return LY_SUCCESS;
1049}
1050
1051/**
1052 * @brief Parse the fraction-digits statement. Substatement of type statement.
1053 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001054 * @param[in] ctx parser context.
1055 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001056 * @param[in,out] fracdig Value to write to.
1057 * @param[in,out] exts Extension instances to add to.
1058 *
1059 * @return LY_ERR values.
1060 */
1061static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001062lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001063 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001064{
1065 char *ptr;
1066 size_t arg_len;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001067 unsigned long long num;
Radek Krejci335332a2019-09-05 13:03:35 +02001068
1069 if (*fracdig) {
1070 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1071 return LY_EVALID;
1072 }
1073
1074 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1075 arg_len = strlen(stmt->arg);
1076 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1077 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1078 return LY_EVALID;
1079 }
1080
1081 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001082 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001083 /* we have not parsed the whole argument */
1084 if ((size_t)(ptr - stmt->arg) != arg_len) {
1085 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1086 return LY_EVALID;
1087 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001088 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001089 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1090 return LY_EVALID;
1091 }
1092 *fracdig = num;
1093
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001094 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1095 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001096 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001097 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001098 break;
1099 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001100 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001101 return LY_EVALID;
1102 }
1103 }
1104 return LY_SUCCESS;
1105}
1106
1107/**
1108 * @brief Parse the require-instance statement. Substatement of type statement.
1109 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001110 * @param[in] ctx parser context.
1111 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001112 * @param[in,out] reqinst Value to write to.
1113 * @param[in,out] flags Flags to write to.
1114 * @param[in,out] exts Extension instances to add to.
1115 *
1116 * @return LY_ERR values.
1117 */
1118static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001119lysp_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 +02001120 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001121{
1122 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001123
1124 if (*flags & LYS_SET_REQINST) {
1125 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1126 return LY_EVALID;
1127 }
1128 *flags |= LYS_SET_REQINST;
1129
1130 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1131 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001132 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001133 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001134 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001135 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1136 return LY_EVALID;
1137 }
1138
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001139 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1140 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001141 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001142 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001143 break;
1144 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001145 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001146 return LY_EVALID;
1147 }
1148 }
1149 return LY_SUCCESS;
1150}
1151
1152/**
1153 * @brief Parse the modifier statement. Substatement of type pattern statement.
1154 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001155 * @param[in] ctx parser context.
1156 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001157 * @param[in,out] pat Value to write to.
1158 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001159 * @return LY_ERR values.
1160 */
1161static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001162lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001163 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001164{
1165 size_t arg_len;
1166 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001167
Radek Krejcif13b87b2020-12-01 22:02:17 +01001168 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001169 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1170 return LY_EVALID;
1171 }
1172
1173 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1174 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001175 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001176 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1177 return LY_EVALID;
1178 }
1179
1180 /* replace the value in the dictionary */
1181 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001182 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001183 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001184 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001185
Radek Krejcif13b87b2020-12-01 22:02:17 +01001186 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1187 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001188 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001189
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001190 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1191 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001192 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001193 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001194 break;
1195 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001196 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001197 return LY_EVALID;
1198 }
1199 }
1200 return LY_SUCCESS;
1201}
1202
1203/**
1204 * @brief Parse the pattern statement. Substatement of type statement.
1205 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001206 * @param[in] ctx parser context.
1207 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001208 * @param[in,out] patterns Restrictions to add to.
1209 *
1210 * @return LY_ERR values.
1211 */
1212static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001213lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001214{
1215 char *buf;
1216 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001217 struct lysp_restr *restr;
1218
1219 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001220 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001221 arg_len = strlen(stmt->arg);
1222
1223 /* add special meaning first byte */
1224 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001225 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001226 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001227 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001228 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001229 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001230 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001231
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001232 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1233 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001234 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001235 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001236 break;
1237 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001238 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001239 break;
1240 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001241 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001242 break;
1243 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001244 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001245 break;
1246 case LY_STMT_MODIFIER:
1247 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001248 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001249 break;
1250 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001251 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001252 break;
1253 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001254 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001255 return LY_EVALID;
1256 }
1257 }
1258 return LY_SUCCESS;
1259}
1260
1261/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001262 * @brief Parse the deviate statement. Substatement of deviation statement.
1263 *
1264 * @param[in] ctx parser context.
1265 * @param[in] stmt Source statement data from the parsed extension instance.
1266 * @param[in,out] devs Array of deviates to add to.
1267 * @param[in,out] exts Extension instances to add to.
1268 * @return LY_ERR values.
1269 */
1270static LY_ERR
1271lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1272{
1273 (void)stmt;
1274 (void)devs;
1275 (void)exts;
1276
1277 /* TODO */
1278 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1279 return LY_EINVAL;
1280}
1281
1282/**
1283 * @brief Parse the deviation statement.
1284 *
1285 * @param[in] ctx parser context.
1286 * @param[in] stmt Source statement data from the parsed extension instance.
1287 * @param[in,out] deviations Array of deviations to add to.
1288 * @return LY_ERR values.
1289 */
1290static LY_ERR
1291lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1292{
1293 struct lysp_deviation *dev;
1294
1295 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1296
1297 /* store nodeid */
1298 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1299 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1300
1301 /* parse substatements */
1302 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1303 switch (child->kw) {
1304 case LY_STMT_DESCRIPTION:
1305 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1306 break;
1307 case LY_STMT_DEVIATE:
1308 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1309 break;
1310 case LY_STMT_REFERENCE:
1311 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1312 break;
1313 case LY_STMT_EXTENSION_INSTANCE:
1314 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1315 break;
1316 default:
1317 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1318 return LY_EVALID;
1319 }
1320 }
1321
1322 return LY_SUCCESS;
1323}
1324
1325/**
1326 * @brief Parse the yang-version statement.
1327 *
1328 * @param[in] ctx parser context.
1329 * @param[in] stmt Source statement data from the parsed extension instance.
1330 * @param[out] version Version to write to.
1331 * @param[in,out] exts Extension instances to add to.
1332 * @return LY_ERR values.
1333 */
1334static LY_ERR
1335lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1336{
1337 if (*version) {
1338 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1339 return LY_EVALID;
1340 }
1341
1342 /* store flag */
1343 if (!strcmp(stmt->arg, "1")) {
1344 *version = LYS_VERSION_1_0;
1345 } else if (!strcmp(stmt->arg, "1.1")) {
1346 *version = LYS_VERSION_1_1;
1347 } else {
1348 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yang-version");
1349 return LY_EVALID;
1350 }
1351
1352 /* parse substatements */
1353 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1354 switch (child->kw) {
1355 case LY_STMT_EXTENSION_INSTANCE:
1356 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1357 break;
1358 default:
1359 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1360 return LY_EVALID;
1361 }
1362 }
1363
1364 return LY_SUCCESS;
1365}
1366
1367/**
1368 * @brief Parse the module statement.
1369 *
1370 * @param[in] ctx parser context.
1371 * @param[in] stmt Source statement data from the parsed extension instance.
1372 * @param[in,out] mod Module to fill.
1373 * @return LY_ERR values.
1374 */
1375static LY_ERR
1376lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1377{
1378 (void)stmt;
1379 (void)mod;
1380
1381 /* TODO */
1382 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1383 return LY_EINVAL;
1384}
1385
1386/**
1387 * @brief Parse the submodule statement.
1388 *
1389 * @param[in] ctx parser context.
1390 * @param[in] stmt Source statement data from the parsed extension instance.
1391 * @param[in,out] submod Module to fill.
1392 * @return LY_ERR values.
1393 */
1394static LY_ERR
1395lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1396{
1397 (void)stmt;
1398 (void)submod;
1399
1400 /* TODO */
1401 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1402 return LY_EINVAL;
1403}
1404
1405/**
1406 * @brief Parse the yin-element statement. Substatement of argument statement.
1407 *
1408 * @param[in] ctx parser context.
1409 * @param[in] stmt Source statement data from the parsed extension instance.
1410 * @param[in,out] flags Flags to write to.
1411 * @param[in,out] exts Extension instances to add to.
1412 * @return LY_ERR values.
1413 */
1414static LY_ERR
1415lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1416{
1417 if (*flags & LYS_YINELEM_MASK) {
1418 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1419 return LY_EVALID;
1420 }
1421
1422 /* store flag */
1423 if (!strcmp(stmt->arg, "true")) {
1424 *flags |= LYS_YINELEM_TRUE;
1425 } else if (!strcmp(stmt->arg, "false")) {
1426 *flags |= LYS_YINELEM_FALSE;
1427 } else {
1428 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yin-element");
1429 return LY_EVALID;
1430 }
1431
1432 /* parse substatements */
1433 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1434 switch (child->kw) {
1435 case LY_STMT_EXTENSION_INSTANCE:
1436 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1437 break;
1438 default:
1439 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1440 return LY_EVALID;
1441 }
1442 }
1443
1444 return LY_SUCCESS;
1445}
1446
1447/**
1448 * @brief Parse the argument statement. Substatement of extension statement.
1449 *
1450 * @param[in] ctx parser context.
1451 * @param[in] stmt Source statement data from the parsed extension instance.
1452 * @param[in,out] ex Extension to fill.
1453 * @return LY_ERR values.
1454 */
1455static LY_ERR
1456lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1457{
1458 if (ex->argname) {
1459 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1460 return LY_EVALID;
1461 }
1462
1463 /* store argument name */
1464 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1465 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1466
1467 /* parse substatements */
1468 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1469 switch (child->kw) {
1470 case LY_STMT_YIN_ELEMENT:
1471 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1472 break;
1473 case LY_STMT_EXTENSION_INSTANCE:
1474 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1475 break;
1476 default:
1477 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1478 return LY_EVALID;
1479 }
1480 }
1481
1482 return LY_SUCCESS;
1483}
1484
1485/**
1486 * @brief Parse the extension statement.
1487 *
1488 * @param[in] ctx parser context.
1489 * @param[in] stmt Source statement data from the parsed extension instance.
1490 * @param[in,out] extensions Array of extensions to add to.
1491 * @return LY_ERR values.
1492 */
1493static LY_ERR
1494lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1495{
1496 struct lysp_ext *ex;
1497
1498 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1499
1500 /* store name */
1501 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1502 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1503
1504 /* parse substatements */
1505 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1506 switch (child->kw) {
1507 case LY_STMT_DESCRIPTION:
1508 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1509 break;
1510 case LY_STMT_REFERENCE:
1511 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1512 break;
1513 case LY_STMT_STATUS:
1514 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1515 break;
1516 case LY_STMT_ARGUMENT:
1517 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1518 break;
1519 case LY_STMT_EXTENSION_INSTANCE:
1520 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1521 break;
1522 default:
1523 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1524 return LY_EVALID;
1525 }
1526 }
1527
1528 return LY_SUCCESS;
1529}
1530
1531/**
1532 * @brief Parse the feature statement.
1533 *
1534 * @param[in] ctx parser context.
1535 * @param[in] stmt Source statement data from the parsed extension instance.
1536 * @param[in,out] features Array of features to add to.
1537 * @return LY_ERR values.
1538 */
1539static LY_ERR
1540lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1541{
1542 struct lysp_feature *feat;
1543
1544 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1545
1546 /* store name */
1547 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1548 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1549
1550 /* parse substatements */
1551 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1552 switch (child->kw) {
1553 case LY_STMT_DESCRIPTION:
1554 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1555 break;
1556 case LY_STMT_IF_FEATURE:
1557 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1558 break;
1559 case LY_STMT_REFERENCE:
1560 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1561 break;
1562 case LY_STMT_STATUS:
1563 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1564 break;
1565 case LY_STMT_EXTENSION_INSTANCE:
1566 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1567 break;
1568 default:
1569 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1570 return LY_EVALID;
1571 }
1572 }
1573
1574 return LY_SUCCESS;
1575}
1576
1577/**
1578 * @brief Parse the identity statement.
1579 *
1580 * @param[in] ctx parser context.
1581 * @param[in] stmt Source statement data from the parsed extension instance.
1582 * @param[in,out] identities Array of identities to add to.
1583 * @return LY_ERR values.
1584 */
1585static LY_ERR
1586lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1587{
1588 struct lysp_ident *ident;
1589
1590 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1591
1592 /* store name */
1593 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1594 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1595
1596 /* parse substatements */
1597 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1598 switch (child->kw) {
1599 case LY_STMT_DESCRIPTION:
1600 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1601 break;
1602 case LY_STMT_IF_FEATURE:
1603 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1604 break;
1605 case LY_STMT_REFERENCE:
1606 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1607 break;
1608 case LY_STMT_STATUS:
1609 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1610 break;
1611 case LY_STMT_BASE:
1612 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1613 break;
1614 case LY_STMT_EXTENSION_INSTANCE:
1615 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1616 break;
1617 default:
1618 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1619 return LY_EVALID;
1620 }
1621 }
1622
1623 return LY_SUCCESS;
1624}
1625
1626/**
1627 * @brief Parse the import statement.
1628 *
1629 * @param[in] ctx parser context.
1630 * @param[in] stmt Source statement data from the parsed extension instance.
1631 * @param[in,out] imports Array of imports to add to.
1632 * @return LY_ERR values.
1633 */
1634static LY_ERR
1635lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1636{
1637 struct lysp_import *imp;
1638 const char *str = NULL;
1639
1640 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1641
1642 /* store name */
1643 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1644 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1645
1646 /* parse substatements */
1647 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1648 switch (child->kw) {
1649 case LY_STMT_PREFIX:
1650 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1651 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1652 break;
1653 case LY_STMT_DESCRIPTION:
1654 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1655 break;
1656 case LY_STMT_REFERENCE:
1657 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1658 break;
1659 case LY_STMT_REVISION_DATE:
1660 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1661 strcpy(imp->rev, str);
1662 lydict_remove(PARSER_CTX(ctx), str);
1663 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1664 break;
1665 case LY_STMT_EXTENSION_INSTANCE:
1666 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1667 break;
1668 default:
1669 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1670 return LY_EVALID;
1671 }
1672 }
1673
1674 return LY_SUCCESS;
1675}
1676
1677/**
1678 * @brief Parse the include statement.
1679 *
1680 * @param[in] ctx parser context.
1681 * @param[in] stmt Source statement data from the parsed extension instance.
1682 * @param[in,out] includes Array of identities to add to.
1683 * @return LY_ERR values.
1684 */
1685static LY_ERR
1686lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1687{
1688 struct lysp_include *inc;
1689 const char *str = NULL;
1690
1691 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1692
1693 /* store name */
1694 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1695 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1696
1697 /* parse substatements */
1698 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1699 switch (child->kw) {
1700 case LY_STMT_DESCRIPTION:
1701 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1702 break;
1703 case LY_STMT_REFERENCE:
1704 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1705 break;
1706 case LY_STMT_REVISION_DATE:
1707 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1708 strcpy(inc->rev, str);
1709 lydict_remove(PARSER_CTX(ctx), str);
1710 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1711 break;
1712 case LY_STMT_EXTENSION_INSTANCE:
1713 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1714 break;
1715 default:
1716 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1717 return LY_EVALID;
1718 }
1719 }
1720
1721 return LY_SUCCESS;
1722}
1723
1724/**
1725 * @brief Parse the revision statement.
1726 *
1727 * @param[in] ctx parser context.
1728 * @param[in] stmt Source statement data from the parsed extension instance.
1729 * @param[in,out] includes Array of identities to add to.
1730 * @return LY_ERR values.
1731 */
1732static LY_ERR
1733lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1734{
1735 struct lysp_revision *rev;
1736
1737 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1738
1739 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001740 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001741 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001742
1743 /* parse substatements */
1744 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1745 switch (child->kw) {
1746 case LY_STMT_DESCRIPTION:
1747 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1748 break;
1749 case LY_STMT_REFERENCE:
1750 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1751 break;
1752 case LY_STMT_EXTENSION_INSTANCE:
1753 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1754 break;
1755 default:
1756 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1757 return LY_EVALID;
1758 }
1759 }
1760
1761 return LY_SUCCESS;
1762}
1763
1764/**
Radek Krejci335332a2019-09-05 13:03:35 +02001765 * @brief Parse the type statement.
1766 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001767 * @param[in] ctx parser context.
1768 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001769 * @param[in,out] type Type to wrote to.
1770 *
1771 * @return LY_ERR values.
1772 */
1773static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001774lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001775{
1776 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001777 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001778 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001779
1780 if (type->name) {
1781 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1782 return LY_EVALID;
1783 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001784
1785 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001786 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001787 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001788
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001789 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1790 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001791 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001792 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001793 type->flags |= LYS_SET_BASE;
1794 break;
1795 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001796 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001797 type->flags |= LYS_SET_BIT;
1798 break;
1799 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001800 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001801 type->flags |= LYS_SET_ENUM;
1802 break;
1803 case LY_STMT_FRACTION_DIGITS:
1804 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1805 type->flags |= LYS_SET_FRDIGITS;
1806 break;
1807 case LY_STMT_LENGTH:
1808 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001809 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001810 return LY_EVALID;
1811 }
1812 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001813 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001814
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001815 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001816 type->flags |= LYS_SET_LENGTH;
1817 break;
1818 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001819 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001820 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001821 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001822 lydict_remove(PARSER_CTX(ctx), str_path);
1823 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001824 type->flags |= LYS_SET_PATH;
1825 break;
1826 case LY_STMT_PATTERN:
1827 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1828 type->flags |= LYS_SET_PATTERN;
1829 break;
1830 case LY_STMT_RANGE:
1831 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001832 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001833 return LY_EVALID;
1834 }
1835 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001836 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001837
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001838 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001839 type->flags |= LYS_SET_RANGE;
1840 break;
1841 case LY_STMT_REQUIRE_INSTANCE:
1842 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001843 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001844 break;
1845 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001846 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001847 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1848 type->flags |= LYS_SET_TYPE;
1849 break;
1850 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001851 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001852 break;
1853 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001854 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001855 return LY_EVALID;
1856 }
1857 }
1858 return LY_SUCCESS;
1859}
1860
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001861/**
1862 * @brief Parse the leaf statement.
1863 *
1864 * @param[in] ctx parser context.
1865 * @param[in] stmt Source statement data from the parsed extension instance.
1866 * @param[in] parent Parent node to connect to (not into).
1867 * @param[in,out] siblings Siblings to add to.
1868 *
1869 * @return LY_ERR values.
1870 */
1871static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001872lysp_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 +01001873{
1874 struct lysp_node_leaf *leaf;
1875
1876 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1877
1878 /* create new leaf structure */
1879 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1880 leaf->nodetype = LYS_LEAF;
1881 leaf->parent = parent;
1882
1883 /* get name */
1884 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1885
1886 /* parse substatements */
1887 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1888 switch (child->kw) {
1889 case LY_STMT_CONFIG:
1890 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1891 break;
1892 case LY_STMT_DEFAULT:
1893 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 +01001894 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001895 break;
1896 case LY_STMT_DESCRIPTION:
1897 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1898 break;
1899 case LY_STMT_IF_FEATURE:
1900 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1901 break;
1902 case LY_STMT_MANDATORY:
1903 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1904 break;
1905 case LY_STMT_MUST:
1906 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1907 break;
1908 case LY_STMT_REFERENCE:
1909 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1910 break;
1911 case LY_STMT_STATUS:
1912 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1913 break;
1914 case LY_STMT_TYPE:
1915 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1916 break;
1917 case LY_STMT_UNITS:
1918 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1919 break;
1920 case LY_STMT_WHEN:
1921 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1922 break;
1923 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001924 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001925 break;
1926 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001927 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001928 return LY_EVALID;
1929 }
1930 }
1931
1932 /* mandatory substatements */
1933 if (!leaf->type.name) {
1934 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1935 return LY_EVALID;
1936 }
1937
1938 return LY_SUCCESS;
1939}
1940
1941/**
1942 * @brief Parse the max-elements statement.
1943 *
1944 * @param[in] ctx parser context.
1945 * @param[in] stmt Source statement data from the parsed extension instance.
1946 * @param[in,out] max Value to write to.
1947 * @param[in,out] flags Flags to write to.
1948 * @param[in,out] exts Extension instances to add to.
1949 *
1950 * @return LY_ERR values.
1951 */
1952static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001953lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
1954 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001955{
1956 size_t arg_len;
1957 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001958 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001959
1960 if (*flags & LYS_SET_MAX) {
1961 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1962 return LY_EVALID;
1963 }
1964 *flags |= LYS_SET_MAX;
1965
1966 /* get value */
1967 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1968 arg_len = strlen(stmt->arg);
1969
1970 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1971 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1972 return LY_EVALID;
1973 }
1974
1975 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1976 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001977 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001978 /* we have not parsed the whole argument */
1979 if ((size_t)(ptr - stmt->arg) != arg_len) {
1980 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1981 return LY_EVALID;
1982 }
1983 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1984 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1985 return LY_EVALID;
1986 }
1987
1988 *max = num;
1989 } else {
1990 /* unbounded */
1991 *max = 0;
1992 }
1993
1994 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1995 switch (child->kw) {
1996 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001997 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001998 break;
1999 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002000 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002001 return LY_EVALID;
2002 }
2003 }
2004
2005 return LY_SUCCESS;
2006}
2007
2008/**
2009 * @brief Parse the min-elements statement.
2010 *
2011 * @param[in] ctx parser context.
2012 * @param[in] stmt Source statement data from the parsed extension instance.
2013 * @param[in,out] min Value to write to.
2014 * @param[in,out] flags Flags to write to.
2015 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002016 * @return LY_ERR values.
2017 */
2018static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002019lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
2020 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002021{
2022 size_t arg_len;
2023 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002024 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002025
2026 if (*flags & LYS_SET_MIN) {
2027 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
2028 return LY_EVALID;
2029 }
2030 *flags |= LYS_SET_MIN;
2031
2032 /* get value */
2033 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2034 arg_len = strlen(stmt->arg);
2035
2036 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
2037 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2038 return LY_EVALID;
2039 }
2040
2041 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002042 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002043 /* we have not parsed the whole argument */
2044 if ((size_t)(ptr - stmt->arg) != arg_len) {
2045 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2046 return LY_EVALID;
2047 }
2048 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2049 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
2050 return LY_EVALID;
2051 }
2052 *min = num;
2053
2054 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2055 switch (child->kw) {
2056 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002057 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002058 break;
2059 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002060 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002061 return LY_EVALID;
2062 }
2063 }
2064
2065 return LY_SUCCESS;
2066}
2067
2068/**
2069 * @brief Parse the ordered-by statement.
2070 *
2071 * @param[in] ctx parser context.
2072 * @param[in] stmt Source statement data from the parsed extension instance.
2073 * @param[in,out] flags Flags to write to.
2074 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002075 * @return LY_ERR values.
2076 */
2077static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002078lysp_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 +01002079{
2080 size_t arg_len;
2081
2082 if (*flags & LYS_ORDBY_MASK) {
2083 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2084 return LY_EVALID;
2085 }
2086
2087 /* get value */
2088 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2089 arg_len = strlen(stmt->arg);
2090 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2091 *flags |= LYS_MAND_TRUE;
2092 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2093 *flags |= LYS_MAND_FALSE;
2094 } else {
2095 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2096 return LY_EVALID;
2097 }
2098
2099 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2100 switch (child->kw) {
2101 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002102 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002103 break;
2104 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002105 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002106 return LY_EVALID;
2107 }
2108 }
2109
2110 return LY_SUCCESS;
2111}
2112
2113/**
2114 * @brief Parse the leaf-list statement.
2115 *
2116 * @param[in] ctx parser context.
2117 * @param[in] stmt Source statement data from the parsed extension instance.
2118 * @param[in] parent Parent node to connect to (not into).
2119 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002120 * @return LY_ERR values.
2121 */
2122static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002123lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002124 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002125{
2126 struct lysp_node_leaflist *llist;
2127
2128 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2129
2130 /* create new leaf-list structure */
2131 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2132 llist->nodetype = LYS_LEAFLIST;
2133 llist->parent = parent;
2134
2135 /* get name */
2136 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2137
2138 /* parse substatements */
2139 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2140 switch (child->kw) {
2141 case LY_STMT_CONFIG:
2142 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2143 break;
2144 case LY_STMT_DEFAULT:
2145 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2146 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2147 break;
2148 case LY_STMT_DESCRIPTION:
2149 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2150 break;
2151 case LY_STMT_IF_FEATURE:
2152 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2153 break;
2154 case LY_STMT_MAX_ELEMENTS:
2155 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2156 break;
2157 case LY_STMT_MIN_ELEMENTS:
2158 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2159 break;
2160 case LY_STMT_MUST:
2161 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2162 break;
2163 case LY_STMT_ORDERED_BY:
2164 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2165 break;
2166 case LY_STMT_REFERENCE:
2167 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2168 break;
2169 case LY_STMT_STATUS:
2170 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2171 break;
2172 case LY_STMT_TYPE:
2173 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2174 break;
2175 case LY_STMT_UNITS:
2176 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2177 break;
2178 case LY_STMT_WHEN:
2179 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2180 break;
2181 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002182 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002183 break;
2184 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002185 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002186 return LY_EVALID;
2187 }
2188 }
2189
2190 /* mandatory substatements */
2191 if (!llist->type.name) {
2192 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2193 return LY_EVALID;
2194 }
2195
2196 return LY_SUCCESS;
2197}
2198
2199/**
2200 * @brief Parse the refine statement.
2201 *
2202 * @param[in] ctx parser context.
2203 * @param[in] stmt Source statement data from the parsed extension instance.
2204 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002205 * @return LY_ERR values.
2206 */
2207static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002208lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002209{
2210 struct lysp_refine *rf;
2211
2212 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2213
2214 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2215
2216 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2217
2218 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2219 switch (child->kw) {
2220 case LY_STMT_CONFIG:
2221 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2222 break;
2223 case LY_STMT_DEFAULT:
2224 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2225 break;
2226 case LY_STMT_DESCRIPTION:
2227 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2228 break;
2229 case LY_STMT_IF_FEATURE:
2230 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2231 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2232 break;
2233 case LY_STMT_MAX_ELEMENTS:
2234 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2235 break;
2236 case LY_STMT_MIN_ELEMENTS:
2237 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2238 break;
2239 case LY_STMT_MUST:
2240 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2241 break;
2242 case LY_STMT_MANDATORY:
2243 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2244 break;
2245 case LY_STMT_REFERENCE:
2246 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2247 break;
2248 case LY_STMT_PRESENCE:
2249 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2250 break;
2251 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002252 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002253 break;
2254 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002255 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002256 return LY_EVALID;
2257 }
2258 }
2259
2260 return LY_SUCCESS;
2261}
2262
2263/**
2264 * @brief Parse the typedef statement.
2265 *
2266 * @param[in] ctx parser context.
2267 * @param[in] stmt Source statement data from the parsed extension instance.
2268 * @param[in] parent Parent node to connect to (not into).
2269 * @param[in,out] typedefs Typedefs to add to.
2270 *
2271 * @return LY_ERR values.
2272 */
2273static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002274lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002275 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002276{
2277 struct lysp_tpdf *tpdf;
2278
2279 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2280
2281 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2282
2283 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2284
2285 /* parse substatements */
2286 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2287 switch (child->kw) {
2288 case LY_STMT_DEFAULT:
2289 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 +01002290 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002291 break;
2292 case LY_STMT_DESCRIPTION:
2293 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2294 break;
2295 case LY_STMT_REFERENCE:
2296 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2297 break;
2298 case LY_STMT_STATUS:
2299 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2300 break;
2301 case LY_STMT_TYPE:
2302 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2303 break;
2304 case LY_STMT_UNITS:
2305 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2306 break;
2307 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002308 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002309 break;
2310 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002311 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002312 return LY_EVALID;
2313 }
2314 }
2315
2316 /* mandatory substatements */
2317 if (!tpdf->type.name) {
2318 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2319 return LY_EVALID;
2320 }
2321
2322 /* store data for collision check */
2323 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2324 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2325 }
2326
2327 return LY_SUCCESS;
2328}
2329
2330/**
2331 * @brief Parse the input or output statement.
2332 *
2333 * @param[in] ctx parser context.
2334 * @param[in] stmt Source statement data from the parsed extension instance.
2335 * @param[in] parent Parent node to connect to (not into).
2336 * @param[in,out] inout_p Input/output pointer to write to.
2337 *
2338 * @return LY_ERR values.
2339 */
2340static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002341lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002342 struct lysp_node_action_inout *inout_p)
2343{
2344 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002345 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002346 return LY_EVALID;
2347 }
2348
2349 /* initiate structure */
2350 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2351 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2352 inout_p->parent = parent;
2353
2354 /* parse substatements */
2355 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2356 switch (child->kw) {
2357 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002358 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002359 /* fall through */
2360 case LY_STMT_ANYXML:
2361 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2362 break;
2363 case LY_STMT_CHOICE:
2364 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2365 break;
2366 case LY_STMT_CONTAINER:
2367 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2368 break;
2369 case LY_STMT_LEAF:
2370 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2371 break;
2372 case LY_STMT_LEAF_LIST:
2373 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2374 break;
2375 case LY_STMT_LIST:
2376 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2377 break;
2378 case LY_STMT_USES:
2379 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2380 break;
2381 case LY_STMT_TYPEDEF:
2382 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2383 break;
2384 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002385 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002386 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2387 break;
2388 case LY_STMT_GROUPING:
2389 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2390 break;
2391 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002392 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002393 break;
2394 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002395 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002396 return LY_EVALID;
2397 }
2398 }
2399
2400 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002401 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002402 return LY_EVALID;
2403 }
2404
2405 return LY_SUCCESS;
2406}
2407
2408/**
2409 * @brief Parse the action statement.
2410 *
2411 * @param[in] ctx parser context.
2412 * @param[in] stmt Source statement data from the parsed extension instance.
2413 * @param[in] parent Parent node to connect to (not into).
2414 * @param[in,out] actions Actions to add to.
2415 *
2416 * @return LY_ERR values.
2417 */
2418static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002419lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002420 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002421{
2422 struct lysp_node_action *act;
2423
2424 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2425
2426 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2427
2428 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2429 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2430 act->parent = parent;
2431
2432 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2433 switch (child->kw) {
2434 case LY_STMT_DESCRIPTION:
2435 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2436 break;
2437 case LY_STMT_IF_FEATURE:
2438 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2439 break;
2440 case LY_STMT_REFERENCE:
2441 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2442 break;
2443 case LY_STMT_STATUS:
2444 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2445 break;
2446
2447 case LY_STMT_INPUT:
2448 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2449 break;
2450 case LY_STMT_OUTPUT:
2451 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2452 break;
2453
2454 case LY_STMT_TYPEDEF:
2455 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2456 break;
2457 case LY_STMT_GROUPING:
2458 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2459 break;
2460 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002461 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 +01002462 break;
2463 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002464 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002465 return LY_EVALID;
2466 }
2467 }
2468
2469 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2470 if (!act->input.nodetype) {
2471 act->input.nodetype = LYS_INPUT;
2472 act->input.parent = &act->node;
2473 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2474 }
2475 if (!act->output.nodetype) {
2476 act->output.nodetype = LYS_OUTPUT;
2477 act->output.parent = &act->node;
2478 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2479 }
2480
2481 return LY_SUCCESS;
2482}
2483
2484/**
2485 * @brief Parse the notification statement.
2486 *
2487 * @param[in] ctx parser context.
2488 * @param[in] stmt Source statement data from the parsed extension instance.
2489 * @param[in] parent Parent node to connect to (not into).
2490 * @param[in,out] notifs Notifications to add to.
2491 *
2492 * @return LY_ERR values.
2493 */
2494static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002495lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002496 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002497{
2498 struct lysp_node_notif *notif;
2499
2500 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2501
2502 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2503
2504 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2505 notif->nodetype = LYS_NOTIF;
2506 notif->parent = parent;
2507
2508 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2509 switch (child->kw) {
2510 case LY_STMT_DESCRIPTION:
2511 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2512 break;
2513 case LY_STMT_IF_FEATURE:
2514 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2515 break;
2516 case LY_STMT_REFERENCE:
2517 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2518 break;
2519 case LY_STMT_STATUS:
2520 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2521 break;
2522
2523 case LY_STMT_ANYDATA:
2524 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2525 /* fall through */
2526 case LY_STMT_ANYXML:
2527 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2528 break;
2529 case LY_STMT_CHOICE:
2530 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2531 break;
2532 case LY_STMT_CONTAINER:
2533 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2534 break;
2535 case LY_STMT_LEAF:
2536 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2537 break;
2538 case LY_STMT_LEAF_LIST:
2539 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2540 break;
2541 case LY_STMT_LIST:
2542 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2543 break;
2544 case LY_STMT_USES:
2545 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2546 break;
2547
2548 case LY_STMT_MUST:
2549 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2550 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2551 break;
2552 case LY_STMT_TYPEDEF:
2553 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2554 break;
2555 case LY_STMT_GROUPING:
2556 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2557 break;
2558 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002559 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002560 break;
2561 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002562 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002563 return LY_EVALID;
2564 }
2565 }
2566
2567 return LY_SUCCESS;
2568}
2569
2570/**
2571 * @brief Parse the grouping statement.
2572 *
2573 * @param[in] ctx parser context.
2574 * @param[in] stmt Source statement data from the parsed extension instance.
2575 * @param[in] parent Parent node to connect to (not into).
2576 * @param[in,out] groupings Groupings to add to.
2577 *
2578 * @return LY_ERR values.
2579 */
2580static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002581lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002582 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002583{
2584 struct lysp_node_grp *grp;
2585
2586 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2587
2588 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2589
2590 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2591 grp->nodetype = LYS_GROUPING;
2592 grp->parent = parent;
2593
2594 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2595 switch (child->kw) {
2596 case LY_STMT_DESCRIPTION:
2597 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2598 break;
2599 case LY_STMT_REFERENCE:
2600 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2601 break;
2602 case LY_STMT_STATUS:
2603 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2604 break;
2605
2606 case LY_STMT_ANYDATA:
2607 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2608 /* fall through */
2609 case LY_STMT_ANYXML:
2610 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2611 break;
2612 case LY_STMT_CHOICE:
2613 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2614 break;
2615 case LY_STMT_CONTAINER:
2616 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2617 break;
2618 case LY_STMT_LEAF:
2619 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2620 break;
2621 case LY_STMT_LEAF_LIST:
2622 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2623 break;
2624 case LY_STMT_LIST:
2625 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2626 break;
2627 case LY_STMT_USES:
2628 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2629 break;
2630
2631 case LY_STMT_TYPEDEF:
2632 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2633 break;
2634 case LY_STMT_ACTION:
2635 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2636 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2637 break;
2638 case LY_STMT_GROUPING:
2639 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2640 break;
2641 case LY_STMT_NOTIFICATION:
2642 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2643 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2644 break;
2645 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002646 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002647 break;
2648 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002649 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002650 return LY_EVALID;
2651 }
2652 }
2653
2654 return LY_SUCCESS;
2655}
2656
2657/**
2658 * @brief Parse the augment statement.
2659 *
2660 * @param[in] ctx parser context.
2661 * @param[in] stmt Source statement data from the parsed extension instance.
2662 * @param[in] parent Parent node to connect to (not into).
2663 * @param[in,out] augments Augments to add to.
2664 *
2665 * @return LY_ERR values.
2666 */
2667static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002668lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002669 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002670{
2671 struct lysp_node_augment *aug;
2672
2673 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2674
2675 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2676
2677 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2678 aug->nodetype = LYS_AUGMENT;
2679 aug->parent = parent;
2680
2681 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2682 switch (child->kw) {
2683 case LY_STMT_DESCRIPTION:
2684 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2685 break;
2686 case LY_STMT_IF_FEATURE:
2687 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2688 break;
2689 case LY_STMT_REFERENCE:
2690 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2691 break;
2692 case LY_STMT_STATUS:
2693 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2694 break;
2695 case LY_STMT_WHEN:
2696 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2697 break;
2698
2699 case LY_STMT_ANYDATA:
2700 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2701 /* fall through */
2702 case LY_STMT_ANYXML:
2703 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2704 break;
2705 case LY_STMT_CASE:
2706 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2707 break;
2708 case LY_STMT_CHOICE:
2709 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2710 break;
2711 case LY_STMT_CONTAINER:
2712 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2713 break;
2714 case LY_STMT_LEAF:
2715 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2716 break;
2717 case LY_STMT_LEAF_LIST:
2718 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2719 break;
2720 case LY_STMT_LIST:
2721 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2722 break;
2723 case LY_STMT_USES:
2724 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2725 break;
2726
2727 case LY_STMT_ACTION:
2728 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2729 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2730 break;
2731 case LY_STMT_NOTIFICATION:
2732 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2733 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2734 break;
2735 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002736 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002737 break;
2738 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002739 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002740 return LY_EVALID;
2741 }
2742 }
2743
2744 return LY_SUCCESS;
2745}
2746
2747/**
2748 * @brief Parse the uses statement.
2749 *
2750 * @param[in] ctx parser context.
2751 * @param[in] stmt Source statement data from the parsed extension instance.
2752 * @param[in] parent Parent node to connect to (not into).
2753 * @param[in,out] siblings Siblings to add to.
2754 *
2755 * @return LY_ERR values.
2756 */
2757static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002758lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002759 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002760{
2761 struct lysp_node_uses *uses;
2762
2763 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2764
2765 /* create uses structure */
2766 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2767
2768 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2769 uses->nodetype = LYS_USES;
2770 uses->parent = parent;
2771
2772 /* parse substatements */
2773 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2774 switch (child->kw) {
2775 case LY_STMT_DESCRIPTION:
2776 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2777 break;
2778 case LY_STMT_IF_FEATURE:
2779 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2780 break;
2781 case LY_STMT_REFERENCE:
2782 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2783 break;
2784 case LY_STMT_STATUS:
2785 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2786 break;
2787 case LY_STMT_WHEN:
2788 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2789 break;
2790
2791 case LY_STMT_REFINE:
2792 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2793 break;
2794 case LY_STMT_AUGMENT:
2795 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2796 break;
2797 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002798 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002799 break;
2800 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002801 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002802 return LY_EVALID;
2803 }
2804 }
2805
2806 return LY_SUCCESS;
2807}
2808
2809/**
2810 * @brief Parse the case statement.
2811 *
2812 * @param[in] ctx parser context.
2813 * @param[in] stmt Source statement data from the parsed extension instance.
2814 * @param[in] parent Parent node to connect to (not into).
2815 * @param[in,out] siblings Siblings to add to.
2816 *
2817 * @return LY_ERR values.
2818 */
2819static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002820lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002821 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002822{
2823 struct lysp_node_case *cas;
2824
2825 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2826
2827 /* create new case structure */
2828 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2829
2830 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2831 cas->nodetype = LYS_CASE;
2832 cas->parent = parent;
2833
2834 /* parse substatements */
2835 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2836 switch (child->kw) {
2837 case LY_STMT_DESCRIPTION:
2838 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2839 break;
2840 case LY_STMT_IF_FEATURE:
2841 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2842 break;
2843 case LY_STMT_REFERENCE:
2844 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2845 break;
2846 case LY_STMT_STATUS:
2847 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2848 break;
2849 case LY_STMT_WHEN:
2850 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2851 break;
2852
2853 case LY_STMT_ANYDATA:
2854 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2855 /* fall through */
2856 case LY_STMT_ANYXML:
2857 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2858 break;
2859 case LY_STMT_CHOICE:
2860 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2861 break;
2862 case LY_STMT_CONTAINER:
2863 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2864 break;
2865 case LY_STMT_LEAF:
2866 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2867 break;
2868 case LY_STMT_LEAF_LIST:
2869 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2870 break;
2871 case LY_STMT_LIST:
2872 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2873 break;
2874 case LY_STMT_USES:
2875 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2876 break;
2877 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002878 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002879 break;
2880 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002881 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002882 return LY_EVALID;
2883 }
2884 }
2885 return LY_SUCCESS;
2886}
2887
2888/**
2889 * @brief Parse the choice statement.
2890 *
2891 * @param[in] ctx parser context.
2892 * @param[in] stmt Source statement data from the parsed extension instance.
2893 * @param[in] parent Parent node to connect to (not into).
2894 * @param[in,out] siblings Siblings to add to.
2895 *
2896 * @return LY_ERR values.
2897 */
2898static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002899lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002900 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002901{
2902 struct lysp_node_choice *choice;
2903
2904 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2905
2906 /* create new choice structure */
2907 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2908
2909 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2910 choice->nodetype = LYS_CHOICE;
2911 choice->parent = parent;
2912
2913 /* parse substatements */
2914 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2915 switch (child->kw) {
2916 case LY_STMT_CONFIG:
2917 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2918 break;
2919 case LY_STMT_DESCRIPTION:
2920 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2921 break;
2922 case LY_STMT_IF_FEATURE:
2923 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2924 break;
2925 case LY_STMT_MANDATORY:
2926 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2927 break;
2928 case LY_STMT_REFERENCE:
2929 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2930 break;
2931 case LY_STMT_STATUS:
2932 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2933 break;
2934 case LY_STMT_WHEN:
2935 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2936 break;
2937 case LY_STMT_DEFAULT:
2938 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 +01002939 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002940 break;
2941 case LY_STMT_ANYDATA:
2942 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2943 /* fall through */
2944 case LY_STMT_ANYXML:
2945 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2946 break;
2947 case LY_STMT_CASE:
2948 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2949 break;
2950 case LY_STMT_CHOICE:
2951 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2952 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2953 break;
2954 case LY_STMT_CONTAINER:
2955 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2956 break;
2957 case LY_STMT_LEAF:
2958 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2959 break;
2960 case LY_STMT_LEAF_LIST:
2961 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2962 break;
2963 case LY_STMT_LIST:
2964 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2965 break;
2966 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002967 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002968 break;
2969 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002970 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002971 return LY_EVALID;
2972 }
2973 }
2974 return LY_SUCCESS;
2975}
2976
2977/**
2978 * @brief Parse the container statement.
2979 *
2980 * @param[in] ctx parser context.
2981 * @param[in] stmt Source statement data from the parsed extension instance.
2982 * @param[in] parent Parent node to connect to (not into).
2983 * @param[in,out] siblings Siblings to add to.
2984 *
2985 * @return LY_ERR values.
2986 */
2987static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002988lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002989 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002990{
2991 struct lysp_node_container *cont;
2992
2993 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2994
2995 /* create new container structure */
2996 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2997
2998 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2999 cont->nodetype = LYS_CONTAINER;
3000 cont->parent = parent;
3001
3002 /* parse substatements */
3003 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3004 switch (child->kw) {
3005 case LY_STMT_CONFIG:
3006 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
3007 break;
3008 case LY_STMT_DESCRIPTION:
3009 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
3010 break;
3011 case LY_STMT_IF_FEATURE:
3012 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
3013 break;
3014 case LY_STMT_REFERENCE:
3015 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
3016 break;
3017 case LY_STMT_STATUS:
3018 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
3019 break;
3020 case LY_STMT_WHEN:
3021 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
3022 break;
3023 case LY_STMT_PRESENCE:
3024 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
3025 break;
3026 case LY_STMT_ANYDATA:
3027 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
3028 /* fall through */
3029 case LY_STMT_ANYXML:
3030 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
3031 break;
3032 case LY_STMT_CHOICE:
3033 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
3034 break;
3035 case LY_STMT_CONTAINER:
3036 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
3037 break;
3038 case LY_STMT_LEAF:
3039 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
3040 break;
3041 case LY_STMT_LEAF_LIST:
3042 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
3043 break;
3044 case LY_STMT_LIST:
3045 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
3046 break;
3047 case LY_STMT_USES:
3048 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
3049 break;
3050
3051 case LY_STMT_TYPEDEF:
3052 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
3053 break;
3054 case LY_STMT_MUST:
3055 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
3056 break;
3057 case LY_STMT_ACTION:
3058 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
3059 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
3060 break;
3061 case LY_STMT_GROUPING:
3062 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3063 break;
3064 case LY_STMT_NOTIFICATION:
3065 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3066 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3067 break;
3068 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003069 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003070 break;
3071 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003072 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003073 return LY_EVALID;
3074 }
3075 }
3076
3077 return LY_SUCCESS;
3078}
3079
3080/**
3081 * @brief Parse the list statement.
3082 *
3083 * @param[in] ctx parser context.
3084 * @param[in] stmt Source statement data from the parsed extension instance.
3085 * @param[in] parent Parent node to connect to (not into).
3086 * @param[in,out] siblings Siblings to add to.
3087 *
3088 * @return LY_ERR values.
3089 */
3090static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003091lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003092 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003093{
3094 struct lysp_node_list *list;
3095
3096 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3097
3098 /* create new list structure */
3099 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3100
3101 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3102 list->nodetype = LYS_LIST;
3103 list->parent = parent;
3104
3105 /* parse substatements */
3106 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3107 switch (child->kw) {
3108 case LY_STMT_CONFIG:
3109 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3110 break;
3111 case LY_STMT_DESCRIPTION:
3112 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3113 break;
3114 case LY_STMT_IF_FEATURE:
3115 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3116 break;
3117 case LY_STMT_REFERENCE:
3118 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3119 break;
3120 case LY_STMT_STATUS:
3121 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3122 break;
3123 case LY_STMT_WHEN:
3124 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3125 break;
3126 case LY_STMT_KEY:
3127 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3128 break;
3129 case LY_STMT_MAX_ELEMENTS:
3130 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3131 break;
3132 case LY_STMT_MIN_ELEMENTS:
3133 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3134 break;
3135 case LY_STMT_ORDERED_BY:
3136 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3137 break;
3138 case LY_STMT_UNIQUE:
3139 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3140 break;
3141
3142 case LY_STMT_ANYDATA:
3143 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3144 /* fall through */
3145 case LY_STMT_ANYXML:
3146 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3147 break;
3148 case LY_STMT_CHOICE:
3149 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3150 break;
3151 case LY_STMT_CONTAINER:
3152 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3153 break;
3154 case LY_STMT_LEAF:
3155 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3156 break;
3157 case LY_STMT_LEAF_LIST:
3158 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3159 break;
3160 case LY_STMT_LIST:
3161 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3162 break;
3163 case LY_STMT_USES:
3164 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3165 break;
3166
3167 case LY_STMT_TYPEDEF:
3168 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3169 break;
3170 case LY_STMT_MUST:
3171 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3172 break;
3173 case LY_STMT_ACTION:
3174 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3175 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3176 break;
3177 case LY_STMT_GROUPING:
3178 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3179 break;
3180 case LY_STMT_NOTIFICATION:
3181 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3182 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3183 break;
3184 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003185 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003186 break;
3187 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003188 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003189 return LY_EVALID;
3190 }
3191 }
3192
3193 return LY_SUCCESS;
3194}
3195
Michal Vasko193dacd2022-10-13 08:43:05 +02003196/**
3197 * @brief Parse generic statement structure into a specific parsed-schema structure.
3198 *
3199 * @param[in] pctx Parse context of the @p stmt being processed.
3200 * @param[in] stmt Generic statement structure to process.
3201 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3202 * @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.
3203 * @return LY_ERR value.
3204 */
3205static LY_ERR
3206lysp_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 +02003207{
Radek Krejciad5963b2019-09-06 16:03:05 +02003208 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003209 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003210
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003211 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003212 case LY_STMT_NOTIFICATION:
3213 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3214 break;
3215 case LY_STMT_INPUT:
3216 case LY_STMT_OUTPUT: {
3217 struct lysp_node_action_inout *inout;
3218
3219 *result = inout = calloc(1, sizeof *inout);
3220 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3221 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3222 break;
3223 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003224 case LY_STMT_ACTION:
3225 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003226 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003227 break;
3228 case LY_STMT_ANYDATA:
3229 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003230 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003231 break;
3232 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003233 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003234 break;
3235 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003236 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003237 break;
3238 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003239 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003240 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003241 case LY_STMT_CONTAINER:
3242 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003243 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003244 case LY_STMT_GROUPING:
3245 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3246 break;
3247 case LY_STMT_LEAF:
3248 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3249 break;
3250 case LY_STMT_LEAF_LIST:
3251 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3252 break;
3253 case LY_STMT_LIST:
3254 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3255 break;
3256 case LY_STMT_USES:
3257 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3258 break;
3259 case LY_STMT_BASE:
3260 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3261 break;
3262 case LY_STMT_ARGUMENT:
3263 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003264 case LY_STMT_CONTACT:
3265 case LY_STMT_DESCRIPTION:
3266 case LY_STMT_ERROR_APP_TAG:
3267 case LY_STMT_ERROR_MESSAGE:
3268 case LY_STMT_KEY:
3269 case LY_STMT_NAMESPACE:
3270 case LY_STMT_ORGANIZATION:
3271 case LY_STMT_PRESENCE:
3272 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003273 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003274 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003275 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003276 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003277 case LY_STMT_BIT:
3278 case LY_STMT_ENUM:
3279 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3280 break;
3281 case LY_STMT_CONFIG:
3282 assert(*result);
3283 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003284 break;
3285 case LY_STMT_DEFAULT:
3286 case LY_STMT_IF_FEATURE:
3287 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003288 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3289 break;
3290 case LY_STMT_DEVIATE:
3291 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3292 break;
3293 case LY_STMT_DEVIATION:
3294 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3295 break;
3296 case LY_STMT_EXTENSION:
3297 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003298 break;
3299 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003300 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3301 break;
3302 case LY_STMT_FEATURE:
3303 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003304 break;
3305 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003306 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003307 break;
3308 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003309 case LY_STMT_RANGE: {
3310 struct lysp_restr *restr;
3311
3312 *result = restr = calloc(1, sizeof *restr);
3313 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3314
3315 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003316 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003317 }
3318 case LY_STMT_MUST:
3319 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3320 break;
3321 case LY_STMT_IDENTITY:
3322 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3323 break;
3324 case LY_STMT_IMPORT:
3325 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3326 break;
3327 case LY_STMT_INCLUDE:
3328 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003329 break;
3330 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003331 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003332 break;
3333 case LY_STMT_MAX_ELEMENTS:
3334 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003335 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003336 break;
3337 case LY_STMT_MIN_ELEMENTS:
3338 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003339 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003340 break;
3341 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003342 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003343 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003344 case LY_STMT_MODULE: {
3345 struct lysp_module *mod;
3346
3347 *result = mod = calloc(1, sizeof *mod);
3348 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3349 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003350 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003351 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003352 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003353 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003354 break;
3355 case LY_STMT_PATH: {
3356 const char *str_path = NULL;
3357
Michal Vasko193dacd2022-10-13 08:43:05 +02003358 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3359 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003360 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003361 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003362 break;
3363 }
3364 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003365 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003366 break;
3367 case LY_STMT_POSITION:
3368 case LY_STMT_VALUE:
3369 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003370 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003371 break;
3372 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003373 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003374 break;
3375 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003376 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003377 break;
3378 case LY_STMT_REQUIRE_INSTANCE:
3379 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003380 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3381 break;
3382 case LY_STMT_REVISION:
3383 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003384 break;
Michal Vasko69730152020-10-09 16:30:07 +02003385 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003386 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003387 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003388 case LY_STMT_SUBMODULE: {
3389 struct lysp_submodule *submod;
3390
3391 *result = submod = calloc(1, sizeof *submod);
3392 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3393 ret = lysp_stmt_submodule(pctx, stmt, submod);
3394 break;
3395 }
Radek Krejci335332a2019-09-05 13:03:35 +02003396 case LY_STMT_TYPE: {
3397 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003398
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003399 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003400 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3401 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003402 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003403 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003404 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003405 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003406 break;
3407 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003408 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3409 break;
3410 case LY_STMT_YANG_VERSION:
3411 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3412 break;
3413 case LY_STMT_YIN_ELEMENT:
3414 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003415 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003416 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003417 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003418 return LY_EINT;
3419 }
3420
Radek Krejciad5963b2019-09-06 16:03:05 +02003421 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003422}
Michal Vasko59892dd2022-05-13 11:02:30 +02003423
Michal Vasko193dacd2022-10-13 08:43:05 +02003424LY_ERR
3425lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003426{
Michal Vasko193dacd2022-10-13 08:43:05 +02003427 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003428
Michal Vasko193dacd2022-10-13 08:43:05 +02003429 if (!substmt->storage) {
3430 /* nothing to parse, ignored */
3431 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003432 }
3433
Michal Vasko193dacd2022-10-13 08:43:05 +02003434 switch (stmt->kw) {
3435 case LY_STMT_NOTIFICATION:
3436 case LY_STMT_INPUT:
3437 case LY_STMT_OUTPUT:
3438 case LY_STMT_ACTION:
3439 case LY_STMT_RPC:
3440 case LY_STMT_ANYDATA:
3441 case LY_STMT_ANYXML:
3442 case LY_STMT_AUGMENT:
3443 case LY_STMT_CASE:
3444 case LY_STMT_CHOICE:
3445 case LY_STMT_CONTAINER:
3446 case LY_STMT_GROUPING:
3447 case LY_STMT_LEAF:
3448 case LY_STMT_LEAF_LIST:
3449 case LY_STMT_LIST:
3450 case LY_STMT_USES: {
3451 struct lysp_node **pnodes_p, *pnode = NULL;
3452
3453 /* parse the node */
3454 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3455
3456 /* usually is a linked-list of all the parsed schema nodes */
3457 pnodes_p = substmt->storage;
3458 while (*pnodes_p) {
3459 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003460 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003461 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003462
3463 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003464 }
3465 case LY_STMT_BASE:
3466 case LY_STMT_BIT:
3467 case LY_STMT_DEFAULT:
3468 case LY_STMT_DEVIATE:
3469 case LY_STMT_DEVIATION:
3470 case LY_STMT_ENUM:
3471 case LY_STMT_EXTENSION:
3472 case LY_STMT_EXTENSION_INSTANCE:
3473 case LY_STMT_FEATURE:
3474 case LY_STMT_IDENTITY:
3475 case LY_STMT_IF_FEATURE:
3476 case LY_STMT_IMPORT:
3477 case LY_STMT_INCLUDE:
3478 case LY_STMT_MUST:
3479 case LY_STMT_PATTERN:
3480 case LY_STMT_REFINE:
3481 case LY_STMT_REVISION:
3482 case LY_STMT_TYPEDEF:
3483 case LY_STMT_UNIQUE:
3484 /* parse, sized array */
3485 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003486 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003487
3488 case LY_STMT_ARGUMENT:
3489 case LY_STMT_BELONGS_TO:
3490 case LY_STMT_CONTACT:
3491 case LY_STMT_DESCRIPTION:
3492 case LY_STMT_ERROR_APP_TAG:
3493 case LY_STMT_ERROR_MESSAGE:
3494 case LY_STMT_FRACTION_DIGITS:
3495 case LY_STMT_KEY:
3496 case LY_STMT_LENGTH:
3497 case LY_STMT_MANDATORY:
3498 case LY_STMT_MAX_ELEMENTS:
3499 case LY_STMT_MIN_ELEMENTS:
3500 case LY_STMT_MODIFIER:
3501 case LY_STMT_MODULE:
3502 case LY_STMT_NAMESPACE:
3503 case LY_STMT_ORGANIZATION:
3504 case LY_STMT_PATH:
3505 case LY_STMT_POSITION:
3506 case LY_STMT_PREFIX:
3507 case LY_STMT_PRESENCE:
3508 case LY_STMT_RANGE:
3509 case LY_STMT_REFERENCE:
3510 case LY_STMT_REQUIRE_INSTANCE:
3511 case LY_STMT_REVISION_DATE:
3512 case LY_STMT_SUBMODULE:
3513 case LY_STMT_TYPE:
3514 case LY_STMT_UNITS:
3515 case LY_STMT_VALUE:
3516 case LY_STMT_WHEN:
3517 case LY_STMT_YANG_VERSION:
3518 case LY_STMT_YIN_ELEMENT:
3519 /* single item */
3520 if (*(void **)substmt->storage) {
3521 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3522 rc = LY_EVALID;
3523 goto cleanup;
3524 }
3525
3526 /* parse */
3527 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003528 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003529
3530 case LY_STMT_CONFIG:
3531 /* single item */
3532 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3533 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3534 rc = LY_EVALID;
3535 goto cleanup;
3536 }
3537
3538 /* parse */
3539 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3540 break;
3541
3542 case LY_STMT_ORDERED_BY:
3543 /* single item */
3544 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3545 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3546 rc = LY_EVALID;
3547 goto cleanup;
3548 }
3549
3550 /* parse */
3551 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3552 break;
3553
3554 case LY_STMT_STATUS:
3555 /* single item */
3556 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3557 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3558 rc = LY_EVALID;
3559 goto cleanup;
3560 }
3561
3562 /* parse */
3563 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3564 break;
3565
Michal Vasko59892dd2022-05-13 11:02:30 +02003566 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003567 LOGINT(PARSER_CTX(pctx));
3568 rc = LY_EINT;
3569 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003570 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003571
3572cleanup:
3573 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003574}