blob: 6fe068b9cb751955aedb11a5593aed3490ea1b1a [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{
183 ly_bool incomplete;
184
185 LY_CHECK_RET(lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node));
186
187 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
188 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
189 }
190 return LY_SUCCESS;
191}
192
193LY_ERR
194lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
195 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
196 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
197{
198 ly_bool incomplete;
199 struct lyd_meta *first = NULL;
200
201 if (meta && *meta) {
202 /* remember the first metadata */
203 first = *meta;
204 }
205
206 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
207 hints, ctx_node, 0, &incomplete));
208
209 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
210 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
211 }
212
213 if (first) {
214 /* always return the first metadata */
215 *meta = first;
216 }
217
218 return LY_SUCCESS;
219}
220
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200221LY_ERR
222lyd_parse_check_keys(struct lyd_node *node)
223{
224 const struct lysc_node *skey = NULL;
225 const struct lyd_node *key;
226
227 assert(node->schema->nodetype == LYS_LIST);
228
229 key = lyd_child(node);
230 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
231 if (!key || (key->schema != skey)) {
232 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
233 return LY_EVALID;
234 }
235
236 key = key->next;
237 }
238
239 return LY_SUCCESS;
240}
241
242LY_ERR
243lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
244 struct lysc_ext_instance *ext)
245{
246 struct lyd_meta *meta2, *prev_meta = NULL;
247 struct lyd_ctx_ext_val *ext_val;
248
Michal Vaskobc9f76f2022-12-01 10:31:38 +0100249 if (lydctx->parse_opts & LYD_PARSE_NO_NEW) {
250 node->flags &= ~LYD_NEW;
251 }
252
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200253 if (lysc_has_when(node->schema)) {
Michal Vaskofbb48c22022-11-30 13:28:03 +0100254 if (lydctx->parse_opts & LYD_PARSE_WHEN_TRUE) {
255 /* the condition was true before */
256 node->flags |= LYD_WHEN_TRUE;
257 }
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200258 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
259 /* remember we need to evaluate this node's when */
260 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
261 }
262 }
263
264 LY_LIST_FOR(*meta, meta2) {
265 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
266 meta2->value.boolean) {
267 /* node is default according to the metadata */
268 node->flags |= LYD_DEFAULT;
269
270 /* delete the metadata */
271 if (prev_meta) {
272 prev_meta->next = meta2->next;
Michal Vasko4754d4a2022-12-01 10:11:21 +0100273 } else if (meta != &node->meta) {
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200274 *meta = (*meta)->next;
275 }
276 lyd_free_meta_single(meta2);
Michal Vasko4754d4a2022-12-01 10:11:21 +0100277
278 /* update dflt flag for all parent NP containers */
279 lyd_cont_set_dflt(lyd_parent(node));
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200280 break;
281 }
282
283 prev_meta = meta2;
284 }
285
286 if (ext) {
287 /* parsed for an extension */
288 node->flags |= LYD_EXT;
289
290 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
291 /* rememeber for validation */
292 ext_val = malloc(sizeof *ext_val);
293 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
294 ext_val->ext = ext;
295 ext_val->sibling = node;
296 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
297 }
298 }
299
300 return LY_SUCCESS;
301}
302
Michal Vasko193dacd2022-10-13 08:43:05 +0200303void
304lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
305{
306 char path[PATH_MAX];
307
308#ifndef __APPLE__
309 char proc_path[32];
310 int len;
311#endif
312
313 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
314 if (*filepath) {
315 /* filepath already set */
316 return;
317 }
318
319 switch (in->type) {
320 case LY_IN_FILEPATH:
321 if (realpath(in->method.fpath.filepath, path) != NULL) {
322 lydict_insert(ctx, path, 0, filepath);
323 } else {
324 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
325 }
326
327 break;
328 case LY_IN_FD:
329#ifdef __APPLE__
330 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
331 lydict_insert(ctx, path, 0, filepath);
332 }
333#elif defined _WIN32
334 HANDLE h = _get_osfhandle(in->method.fd);
335 FILE_NAME_INFO info;
Michal Vasko2bf4af42023-01-04 12:08:38 +0100336
Michal Vasko193dacd2022-10-13 08:43:05 +0200337 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
338 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
Michal Vasko2bf4af42023-01-04 12:08:38 +0100339
Michal Vasko193dacd2022-10-13 08:43:05 +0200340 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
341 lydict_insert(ctx, buf, len, filepath);
342 }
343#else
344 /* get URI if there is /proc */
345 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
346 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
347 lydict_insert(ctx, path, len, filepath);
348 }
349#endif
350 break;
351 case LY_IN_MEMORY:
352 case LY_IN_FILE:
353 /* nothing to do */
354 break;
355 default:
356 LOGINT(ctx);
357 break;
358 }
359}
360
Michal Vaskod0625d72022-10-06 15:02:50 +0200361static 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 +0100362 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200363static 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 +0100364 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200365static 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 +0100366 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200367static 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 +0100368 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200369static 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 +0100370 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200371static 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 +0100372 struct lysp_node **siblings);
373
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100374/**
375 * @brief Validate stmt string value.
376 *
377 * @param[in] ctx Parser context.
378 * @param[in] val_type String value type.
379 * @param[in] val Value to validate.
380 * @return LY_ERR value.
381 */
Radek Krejci335332a2019-09-05 13:03:35 +0200382static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200383lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200384{
Radek Krejci857189e2020-09-01 13:26:36 +0200385 uint8_t prefix = 0;
386 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200387 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200388 size_t utf8_char_len;
389
390 while (*val) {
391 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200392 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200393
394 switch (val_type) {
395 case Y_IDENTIF_ARG:
396 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
397 break;
398 case Y_PREF_IDENTIF_ARG:
399 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
400 break;
401 case Y_STR_ARG:
402 case Y_MAYBE_STR_ARG:
403 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
404 break;
405 }
406 first = 0;
407 }
408
409 return LY_SUCCESS;
410}
411
412/**
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100413 * @brief Duplicate statement siblings, recursively.
414 *
415 * @param[in] ctx Parser context.
416 * @param[in] stmt Statement to duplicate.
417 * @param[out] first First duplicated statement, the rest follow.
418 * @return LY_ERR value.
419 */
420static LY_ERR
421lysp_stmt_dup(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_stmt **first)
422{
423 struct lysp_stmt *child, *last = NULL;
424
425 LY_LIST_FOR(stmt, stmt) {
426 child = calloc(1, sizeof *child);
427 LY_CHECK_ERR_RET(!child, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
428
429 if (last) {
430 last->next = child;
431 } else {
432 assert(!*first);
433 *first = child;
434 }
435 last = child;
436
437 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &child->stmt));
438 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &child->arg));
439 child->format = stmt->format;
440 LY_CHECK_RET(ly_dup_prefix_data(PARSER_CTX(ctx), stmt->format, stmt->prefix_data, &child->prefix_data));
441 child->flags = stmt->flags;
442 child->kw = stmt->kw;
443
444 /* recursively */
445 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &child->child));
446 }
447
448 return LY_SUCCESS;
449}
450
451/**
Radek Krejci335332a2019-09-05 13:03:35 +0200452 * @brief Parse extension instance.
453 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100454 * @param[in] ctx parser context.
455 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100456 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200457 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
458 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200459 * @return LY_ERR values.
460 */
461static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200462lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200463 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200464{
465 struct lysp_ext_instance *e;
466
Michal Vaskob36053d2020-03-26 15:49:30 +0100467 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200468
469 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200470 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100471 e->parent_stmt = insubstmt;
472 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200473 e->parsed = NULL;
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100474 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &e->child));
Radek Krejci335332a2019-09-05 13:03:35 +0200475
476 /* get optional argument */
477 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200478 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200479 }
480
481 return LY_SUCCESS;
482}
483
484/**
485 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
486 * description, etc...
487 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100488 * @param[in] ctx parser context.
489 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200490 * @param[in] substmt_index Index of this substatement.
491 * @param[in,out] value Place to store the parsed value.
492 * @param[in] arg Type of the YANG keyword argument (of the value).
493 * @param[in,out] exts Extension instances to add to.
494 *
495 * @return LY_ERR values.
496 */
497static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200498lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
499 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200500{
Radek Krejci335332a2019-09-05 13:03:35 +0200501 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200502 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200503 return LY_EVALID;
504 }
505
506 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200507 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200508
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100509 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
510 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200511 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100512 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200513 break;
514 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200515 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200516 return LY_EVALID;
517 }
518 }
519 return LY_SUCCESS;
520}
521
522/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200523 * @brief Parse a qname that can have more instances such as if-feature.
524 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100525 * @param[in] ctx parser context.
526 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200527 * @param[in,out] qnames Parsed qnames to add to.
528 * @param[in] arg Type of the expected argument.
529 * @param[in,out] exts Extension instances to add to.
530 *
531 * @return LY_ERR values.
532 */
533static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200534lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
535 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200536{
537 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200538
539 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
540
541 /* allocate new pointer */
542 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
543 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100544 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200545
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100546 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
547 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200548 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100549 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200550 break;
551 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200552 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200553 return LY_EVALID;
554 }
555 }
556 return LY_SUCCESS;
557}
558
559/**
Radek Krejci335332a2019-09-05 13:03:35 +0200560 * @brief Parse a generic text field that can have more instances such as base.
561 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100562 * @param[in] ctx parser context.
563 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200564 * @param[in,out] texts Parsed values to add to.
565 * @param[in] arg Type of the expected argument.
566 * @param[in,out] exts Extension instances to add to.
567 *
568 * @return LY_ERR values.
569 */
570static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200571lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
572 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200573{
574 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200575
576 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
577
578 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100579 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200580 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200581
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100582 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
583 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200584 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100585 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200586 break;
587 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200588 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200589 return LY_EVALID;
590 }
591 }
592 return LY_SUCCESS;
593}
594
595/**
596 * @brief Parse the status statement.
597 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100598 * @param[in] ctx parser context.
599 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200600 * @param[in,out] flags Flags to add to.
601 * @param[in,out] exts Extension instances to add to.
602 *
603 * @return LY_ERR values.
604 */
605static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200606lysp_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 +0200607{
608 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200609
610 if (*flags & LYS_STATUS_MASK) {
611 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
612 return LY_EVALID;
613 }
614
615 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
616 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100617 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200618 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100619 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200620 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100621 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200622 *flags |= LYS_STATUS_OBSLT;
623 } else {
624 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
625 return LY_EVALID;
626 }
627
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100628 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
629 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200630 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100631 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200632 break;
633 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200634 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200635 return LY_EVALID;
636 }
637 }
638 return LY_SUCCESS;
639}
640
641/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100642 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200643 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100644 * @param[in] ctx parser context.
645 * @param[in] stmt Source statement data from the parsed extension instance.
646 * @param[in,out] when_p When pointer to parse to.
647 *
648 * @return LY_ERR values.
649 */
650static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200651lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100652{
653 LY_ERR ret = LY_SUCCESS;
654 struct lysp_when *when;
655
656 if (*when_p) {
657 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
658 return LY_EVALID;
659 }
660
661 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
662
663 when = calloc(1, sizeof *when);
664 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
665 *when_p = when;
666
667 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
668
669 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
670 switch (child->kw) {
671 case LY_STMT_DESCRIPTION:
672 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
673 break;
674 case LY_STMT_REFERENCE:
675 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
676 break;
677 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100678 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100679 break;
680 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200681 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100682 return LY_EVALID;
683 }
684 }
685 return ret;
686}
687
688/**
689 * @brief Parse the config statement.
690 *
691 * @param[in] ctx parser context.
692 * @param[in] stmt Source statement data from the parsed extension instance.
693 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200694 * @param[in,out] exts Extension instances to add to.
695 *
696 * @return LY_ERR values.
697 */
698static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200699lysp_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 +0200700{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100701 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200702
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100703 if (*flags & LYS_CONFIG_MASK) {
704 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
705 return LY_EVALID;
706 }
707
708 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
709 arg_len = strlen(stmt->arg);
710 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
711 *flags |= LYS_CONFIG_W;
712 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
713 *flags |= LYS_CONFIG_R;
714 } else {
715 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
716 return LY_EVALID;
717 }
718
719 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
720 switch (child->kw) {
721 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100722 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100723 break;
724 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200725 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100726 return LY_EVALID;
727 }
728 }
729
730 return LY_SUCCESS;
731}
732
733/**
734 * @brief Parse the mandatory statement.
735 *
736 * @param[in] ctx parser context.
737 * @param[in] stmt Source statement data from the parsed extension instance.
738 * @param[in,out] flags Flags to add to.
739 * @param[in,out] exts Extension instances to add to.
740 *
741 * @return LY_ERR values.
742 */
743static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200744lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200745 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100746{
747 size_t arg_len;
748
749 if (*flags & LYS_MAND_MASK) {
750 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
751 return LY_EVALID;
752 }
753
754 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
755 arg_len = strlen(stmt->arg);
756 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
757 *flags |= LYS_MAND_TRUE;
758 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
759 *flags |= LYS_MAND_FALSE;
760 } else {
761 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
762 return LY_EVALID;
763 }
764
765 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
766 switch (child->kw) {
767 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100768 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100769 break;
770 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200771 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100772 return LY_EVALID;
773 }
774 }
775
776 return LY_SUCCESS;
777}
778
779/**
780 * @brief Parse a restriction such as range or length.
781 *
782 * @param[in] ctx parser context.
783 * @param[in] stmt Source statement data from the parsed extension instance.
784 * @param[in,out] exts Extension instances to add to.
785 *
786 * @return LY_ERR values.
787 */
788static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200789lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100790{
Radek Krejci335332a2019-09-05 13:03:35 +0200791 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200792 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100793 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200794
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100795 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
796 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200797 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100798 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200799 break;
800 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100801 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200802 break;
803 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100804 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200805 break;
806 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100807 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200808 break;
809 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100810 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200811 break;
812 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200813 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200814 return LY_EVALID;
815 }
816 }
817 return LY_SUCCESS;
818}
819
820/**
821 * @brief Parse a restriction that can have more instances such as must.
822 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100823 * @param[in] ctx parser context.
824 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200825 * @param[in,out] restrs Restrictions to add to.
826 *
827 * @return LY_ERR values.
828 */
829static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200830lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200831{
832 struct lysp_restr *restr;
833
Michal Vaskob36053d2020-03-26 15:49:30 +0100834 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100835 return lysp_stmt_restr(ctx, stmt, restr);
836}
837
838/**
839 * @brief Parse the anydata or anyxml statement.
840 *
841 * @param[in] ctx parser context.
842 * @param[in] stmt Source statement data from the parsed extension instance.
843 * @param[in,out] siblings Siblings to add to.
844 *
845 * @return LY_ERR values.
846 */
847static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200848lysp_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 +0100849{
850 struct lysp_node_anydata *any;
851
852 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
853
854 /* create new structure and insert into siblings */
855 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
856
857 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
858 any->parent = parent;
859
860 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
861
862 /* parse substatements */
863 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
864 switch (child->kw) {
865 case LY_STMT_CONFIG:
866 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
867 break;
868 case LY_STMT_DESCRIPTION:
869 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
870 break;
871 case LY_STMT_IF_FEATURE:
872 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
873 break;
874 case LY_STMT_MANDATORY:
875 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
876 break;
877 case LY_STMT_MUST:
878 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
879 break;
880 case LY_STMT_REFERENCE:
881 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
882 break;
883 case LY_STMT_STATUS:
884 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
885 break;
886 case LY_STMT_WHEN:
887 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
888 break;
889 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100890 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100891 break;
892 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200893 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
894 (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 +0100895 return LY_EVALID;
896 }
897 }
898
899 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200900}
901
902/**
903 * @brief Parse the value or position statement. Substatement of type enum statement.
904 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100905 * @param[in] ctx parser context.
906 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200907 * @param[in,out] value Value to write to.
908 * @param[in,out] flags Flags to write to.
909 * @param[in,out] exts Extension instances to add to.
910 *
911 * @return LY_ERR values.
912 */
913static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200914lysp_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 +0200915 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200916{
917 size_t arg_len;
918 char *ptr = NULL;
Michal Vasko2bf4af42023-01-04 12:08:38 +0100919 long long num = 0;
920 unsigned long long unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200921
922 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200923 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200924 return LY_EVALID;
925 }
926 *flags |= LYS_SET_VALUE;
927
928 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
929
930 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100931 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
932 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200933 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200934 goto error;
935 }
936
937 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100938 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200939 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200940 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200941 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200942 goto error;
943 }
944 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200945 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200946 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200947 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200948 goto error;
949 }
950 }
951 /* we have not parsed the whole argument */
952 if ((size_t)(ptr - stmt->arg) != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200953 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200954 goto error;
955 }
956 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200957 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200958 goto error;
959 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100960 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200961 *value = num;
962 } else {
963 *value = unum;
964 }
965
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100966 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
967 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200968 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100969 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw == LY_STMT_VALUE ? LY_STMT_VALUE : LY_STMT_POSITION, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200970 break;
971 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200972 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200973 return LY_EVALID;
974 }
975 }
976 return LY_SUCCESS;
977
978error:
979 return LY_EVALID;
980}
981
982/**
983 * @brief Parse the enum or bit statement. Substatement of type statement.
984 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100985 * @param[in] ctx parser context.
986 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200987 * @param[in,out] enums Enums or bits to add to.
988 *
989 * @return LY_ERR values.
990 */
991static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200992lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +0200993{
994 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200995
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100996 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 +0200997
Michal Vaskob36053d2020-03-26 15:49:30 +0100998 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200999
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001000 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +02001001 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
1002 } /* else nothing specific for YANG_BIT */
1003
Radek Krejci011e4aa2020-09-04 15:22:31 +02001004 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +02001005 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +02001006
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001007 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1008 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001009 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001010 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001011 break;
1012 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001013 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001014 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001015 break;
1016 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001017 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001018 break;
1019 case LY_STMT_STATUS:
1020 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
1021 break;
1022 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001023 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1024 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001025 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001026 break;
1027 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +02001028 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1029 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001030 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001031 break;
1032 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001033 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001034 break;
1035 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001036 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001037 return LY_EVALID;
1038 }
1039 }
Michal Vasko193dacd2022-10-13 08:43:05 +02001040
Radek Krejci335332a2019-09-05 13:03:35 +02001041 return LY_SUCCESS;
1042}
1043
1044/**
1045 * @brief Parse the fraction-digits statement. Substatement of type statement.
1046 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001047 * @param[in] ctx parser context.
1048 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001049 * @param[in,out] fracdig Value to write to.
1050 * @param[in,out] exts Extension instances to add to.
1051 *
1052 * @return LY_ERR values.
1053 */
1054static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001055lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001056 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001057{
1058 char *ptr;
1059 size_t arg_len;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001060 unsigned long long num;
Radek Krejci335332a2019-09-05 13:03:35 +02001061
1062 if (*fracdig) {
1063 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1064 return LY_EVALID;
1065 }
1066
1067 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1068 arg_len = strlen(stmt->arg);
1069 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1070 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1071 return LY_EVALID;
1072 }
1073
1074 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001075 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001076 /* we have not parsed the whole argument */
1077 if ((size_t)(ptr - stmt->arg) != arg_len) {
1078 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1079 return LY_EVALID;
1080 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001081 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001082 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1083 return LY_EVALID;
1084 }
1085 *fracdig = num;
1086
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001087 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1088 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001089 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001090 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001091 break;
1092 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001093 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001094 return LY_EVALID;
1095 }
1096 }
1097 return LY_SUCCESS;
1098}
1099
1100/**
1101 * @brief Parse the require-instance statement. Substatement of type statement.
1102 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001103 * @param[in] ctx parser context.
1104 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001105 * @param[in,out] reqinst Value to write to.
1106 * @param[in,out] flags Flags to write to.
1107 * @param[in,out] exts Extension instances to add to.
1108 *
1109 * @return LY_ERR values.
1110 */
1111static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001112lysp_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 +02001113 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001114{
1115 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001116
1117 if (*flags & LYS_SET_REQINST) {
1118 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1119 return LY_EVALID;
1120 }
1121 *flags |= LYS_SET_REQINST;
1122
1123 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1124 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001125 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001126 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001127 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001128 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1129 return LY_EVALID;
1130 }
1131
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001132 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1133 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001134 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001135 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001136 break;
1137 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001138 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001139 return LY_EVALID;
1140 }
1141 }
1142 return LY_SUCCESS;
1143}
1144
1145/**
1146 * @brief Parse the modifier statement. Substatement of type pattern statement.
1147 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001148 * @param[in] ctx parser context.
1149 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001150 * @param[in,out] pat Value to write to.
1151 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001152 * @return LY_ERR values.
1153 */
1154static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001155lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001156 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001157{
1158 size_t arg_len;
1159 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001160
Radek Krejcif13b87b2020-12-01 22:02:17 +01001161 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001162 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1163 return LY_EVALID;
1164 }
1165
1166 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1167 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001168 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001169 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1170 return LY_EVALID;
1171 }
1172
1173 /* replace the value in the dictionary */
1174 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001175 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001176 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001177 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001178
Radek Krejcif13b87b2020-12-01 22:02:17 +01001179 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1180 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001181 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001182
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001183 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1184 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001185 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001186 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001187 break;
1188 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001189 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001190 return LY_EVALID;
1191 }
1192 }
1193 return LY_SUCCESS;
1194}
1195
1196/**
1197 * @brief Parse the pattern statement. Substatement of type statement.
1198 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001199 * @param[in] ctx parser context.
1200 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001201 * @param[in,out] patterns Restrictions to add to.
1202 *
1203 * @return LY_ERR values.
1204 */
1205static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001206lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001207{
1208 char *buf;
1209 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001210 struct lysp_restr *restr;
1211
1212 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001213 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001214 arg_len = strlen(stmt->arg);
1215
1216 /* add special meaning first byte */
1217 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001218 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001219 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001220 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001221 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001222 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001223 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001224
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001225 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1226 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001227 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001228 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001229 break;
1230 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001231 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001232 break;
1233 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001234 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001235 break;
1236 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001237 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001238 break;
1239 case LY_STMT_MODIFIER:
1240 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001241 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001242 break;
1243 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001244 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001245 break;
1246 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001247 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001248 return LY_EVALID;
1249 }
1250 }
1251 return LY_SUCCESS;
1252}
1253
1254/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001255 * @brief Parse the deviate statement. Substatement of deviation statement.
1256 *
1257 * @param[in] ctx parser context.
1258 * @param[in] stmt Source statement data from the parsed extension instance.
1259 * @param[in,out] devs Array of deviates to add to.
1260 * @param[in,out] exts Extension instances to add to.
1261 * @return LY_ERR values.
1262 */
1263static LY_ERR
1264lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1265{
1266 (void)stmt;
1267 (void)devs;
1268 (void)exts;
1269
1270 /* TODO */
1271 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1272 return LY_EINVAL;
1273}
1274
1275/**
1276 * @brief Parse the deviation statement.
1277 *
1278 * @param[in] ctx parser context.
1279 * @param[in] stmt Source statement data from the parsed extension instance.
1280 * @param[in,out] deviations Array of deviations to add to.
1281 * @return LY_ERR values.
1282 */
1283static LY_ERR
1284lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1285{
1286 struct lysp_deviation *dev;
1287
1288 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1289
1290 /* store nodeid */
1291 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1292 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1293
1294 /* parse substatements */
1295 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1296 switch (child->kw) {
1297 case LY_STMT_DESCRIPTION:
1298 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1299 break;
1300 case LY_STMT_DEVIATE:
1301 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1302 break;
1303 case LY_STMT_REFERENCE:
1304 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1305 break;
1306 case LY_STMT_EXTENSION_INSTANCE:
1307 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1308 break;
1309 default:
1310 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1311 return LY_EVALID;
1312 }
1313 }
1314
1315 return LY_SUCCESS;
1316}
1317
1318/**
1319 * @brief Parse the yang-version statement.
1320 *
1321 * @param[in] ctx parser context.
1322 * @param[in] stmt Source statement data from the parsed extension instance.
1323 * @param[out] version Version to write to.
1324 * @param[in,out] exts Extension instances to add to.
1325 * @return LY_ERR values.
1326 */
1327static LY_ERR
1328lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1329{
1330 if (*version) {
1331 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1332 return LY_EVALID;
1333 }
1334
1335 /* store flag */
1336 if (!strcmp(stmt->arg, "1")) {
1337 *version = LYS_VERSION_1_0;
1338 } else if (!strcmp(stmt->arg, "1.1")) {
1339 *version = LYS_VERSION_1_1;
1340 } else {
1341 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yang-version");
1342 return LY_EVALID;
1343 }
1344
1345 /* parse substatements */
1346 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1347 switch (child->kw) {
1348 case LY_STMT_EXTENSION_INSTANCE:
1349 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1350 break;
1351 default:
1352 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1353 return LY_EVALID;
1354 }
1355 }
1356
1357 return LY_SUCCESS;
1358}
1359
1360/**
1361 * @brief Parse the module statement.
1362 *
1363 * @param[in] ctx parser context.
1364 * @param[in] stmt Source statement data from the parsed extension instance.
1365 * @param[in,out] mod Module to fill.
1366 * @return LY_ERR values.
1367 */
1368static LY_ERR
1369lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1370{
1371 (void)stmt;
1372 (void)mod;
1373
1374 /* TODO */
1375 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1376 return LY_EINVAL;
1377}
1378
1379/**
1380 * @brief Parse the submodule statement.
1381 *
1382 * @param[in] ctx parser context.
1383 * @param[in] stmt Source statement data from the parsed extension instance.
1384 * @param[in,out] submod Module to fill.
1385 * @return LY_ERR values.
1386 */
1387static LY_ERR
1388lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1389{
1390 (void)stmt;
1391 (void)submod;
1392
1393 /* TODO */
1394 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1395 return LY_EINVAL;
1396}
1397
1398/**
1399 * @brief Parse the yin-element statement. Substatement of argument statement.
1400 *
1401 * @param[in] ctx parser context.
1402 * @param[in] stmt Source statement data from the parsed extension instance.
1403 * @param[in,out] flags Flags to write to.
1404 * @param[in,out] exts Extension instances to add to.
1405 * @return LY_ERR values.
1406 */
1407static LY_ERR
1408lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1409{
1410 if (*flags & LYS_YINELEM_MASK) {
1411 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1412 return LY_EVALID;
1413 }
1414
1415 /* store flag */
1416 if (!strcmp(stmt->arg, "true")) {
1417 *flags |= LYS_YINELEM_TRUE;
1418 } else if (!strcmp(stmt->arg, "false")) {
1419 *flags |= LYS_YINELEM_FALSE;
1420 } else {
1421 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yin-element");
1422 return LY_EVALID;
1423 }
1424
1425 /* parse substatements */
1426 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1427 switch (child->kw) {
1428 case LY_STMT_EXTENSION_INSTANCE:
1429 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1430 break;
1431 default:
1432 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1433 return LY_EVALID;
1434 }
1435 }
1436
1437 return LY_SUCCESS;
1438}
1439
1440/**
1441 * @brief Parse the argument statement. Substatement of extension statement.
1442 *
1443 * @param[in] ctx parser context.
1444 * @param[in] stmt Source statement data from the parsed extension instance.
1445 * @param[in,out] ex Extension to fill.
1446 * @return LY_ERR values.
1447 */
1448static LY_ERR
1449lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1450{
1451 if (ex->argname) {
1452 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1453 return LY_EVALID;
1454 }
1455
1456 /* store argument name */
1457 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1458 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1459
1460 /* parse substatements */
1461 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1462 switch (child->kw) {
1463 case LY_STMT_YIN_ELEMENT:
1464 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1465 break;
1466 case LY_STMT_EXTENSION_INSTANCE:
1467 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1468 break;
1469 default:
1470 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1471 return LY_EVALID;
1472 }
1473 }
1474
1475 return LY_SUCCESS;
1476}
1477
1478/**
1479 * @brief Parse the extension statement.
1480 *
1481 * @param[in] ctx parser context.
1482 * @param[in] stmt Source statement data from the parsed extension instance.
1483 * @param[in,out] extensions Array of extensions to add to.
1484 * @return LY_ERR values.
1485 */
1486static LY_ERR
1487lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1488{
1489 struct lysp_ext *ex;
1490
1491 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1492
1493 /* store name */
1494 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1495 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1496
1497 /* parse substatements */
1498 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1499 switch (child->kw) {
1500 case LY_STMT_DESCRIPTION:
1501 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1502 break;
1503 case LY_STMT_REFERENCE:
1504 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1505 break;
1506 case LY_STMT_STATUS:
1507 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1508 break;
1509 case LY_STMT_ARGUMENT:
1510 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1511 break;
1512 case LY_STMT_EXTENSION_INSTANCE:
1513 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1514 break;
1515 default:
1516 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1517 return LY_EVALID;
1518 }
1519 }
1520
1521 return LY_SUCCESS;
1522}
1523
1524/**
1525 * @brief Parse the feature statement.
1526 *
1527 * @param[in] ctx parser context.
1528 * @param[in] stmt Source statement data from the parsed extension instance.
1529 * @param[in,out] features Array of features to add to.
1530 * @return LY_ERR values.
1531 */
1532static LY_ERR
1533lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1534{
1535 struct lysp_feature *feat;
1536
1537 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1538
1539 /* store name */
1540 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1541 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1542
1543 /* parse substatements */
1544 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1545 switch (child->kw) {
1546 case LY_STMT_DESCRIPTION:
1547 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1548 break;
1549 case LY_STMT_IF_FEATURE:
1550 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1551 break;
1552 case LY_STMT_REFERENCE:
1553 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1554 break;
1555 case LY_STMT_STATUS:
1556 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1557 break;
1558 case LY_STMT_EXTENSION_INSTANCE:
1559 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1560 break;
1561 default:
1562 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1563 return LY_EVALID;
1564 }
1565 }
1566
1567 return LY_SUCCESS;
1568}
1569
1570/**
1571 * @brief Parse the identity statement.
1572 *
1573 * @param[in] ctx parser context.
1574 * @param[in] stmt Source statement data from the parsed extension instance.
1575 * @param[in,out] identities Array of identities to add to.
1576 * @return LY_ERR values.
1577 */
1578static LY_ERR
1579lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1580{
1581 struct lysp_ident *ident;
1582
1583 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1584
1585 /* store name */
1586 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1587 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1588
1589 /* parse substatements */
1590 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1591 switch (child->kw) {
1592 case LY_STMT_DESCRIPTION:
1593 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1594 break;
1595 case LY_STMT_IF_FEATURE:
1596 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1597 break;
1598 case LY_STMT_REFERENCE:
1599 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1600 break;
1601 case LY_STMT_STATUS:
1602 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1603 break;
1604 case LY_STMT_BASE:
1605 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1606 break;
1607 case LY_STMT_EXTENSION_INSTANCE:
1608 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1609 break;
1610 default:
1611 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1612 return LY_EVALID;
1613 }
1614 }
1615
1616 return LY_SUCCESS;
1617}
1618
1619/**
1620 * @brief Parse the import statement.
1621 *
1622 * @param[in] ctx parser context.
1623 * @param[in] stmt Source statement data from the parsed extension instance.
1624 * @param[in,out] imports Array of imports to add to.
1625 * @return LY_ERR values.
1626 */
1627static LY_ERR
1628lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1629{
1630 struct lysp_import *imp;
1631 const char *str = NULL;
1632
1633 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1634
1635 /* store name */
1636 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1637 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1638
1639 /* parse substatements */
1640 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1641 switch (child->kw) {
1642 case LY_STMT_PREFIX:
1643 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1644 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1645 break;
1646 case LY_STMT_DESCRIPTION:
1647 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1648 break;
1649 case LY_STMT_REFERENCE:
1650 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1651 break;
1652 case LY_STMT_REVISION_DATE:
1653 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1654 strcpy(imp->rev, str);
1655 lydict_remove(PARSER_CTX(ctx), str);
1656 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1657 break;
1658 case LY_STMT_EXTENSION_INSTANCE:
1659 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1660 break;
1661 default:
1662 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1663 return LY_EVALID;
1664 }
1665 }
1666
1667 return LY_SUCCESS;
1668}
1669
1670/**
1671 * @brief Parse the include statement.
1672 *
1673 * @param[in] ctx parser context.
1674 * @param[in] stmt Source statement data from the parsed extension instance.
1675 * @param[in,out] includes Array of identities to add to.
1676 * @return LY_ERR values.
1677 */
1678static LY_ERR
1679lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1680{
1681 struct lysp_include *inc;
1682 const char *str = NULL;
1683
1684 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1685
1686 /* store name */
1687 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1688 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1689
1690 /* parse substatements */
1691 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1692 switch (child->kw) {
1693 case LY_STMT_DESCRIPTION:
1694 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1695 break;
1696 case LY_STMT_REFERENCE:
1697 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1698 break;
1699 case LY_STMT_REVISION_DATE:
1700 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1701 strcpy(inc->rev, str);
1702 lydict_remove(PARSER_CTX(ctx), str);
1703 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1704 break;
1705 case LY_STMT_EXTENSION_INSTANCE:
1706 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1707 break;
1708 default:
1709 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1710 return LY_EVALID;
1711 }
1712 }
1713
1714 return LY_SUCCESS;
1715}
1716
1717/**
1718 * @brief Parse the revision statement.
1719 *
1720 * @param[in] ctx parser context.
1721 * @param[in] stmt Source statement data from the parsed extension instance.
1722 * @param[in,out] includes Array of identities to add to.
1723 * @return LY_ERR values.
1724 */
1725static LY_ERR
1726lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1727{
1728 struct lysp_revision *rev;
1729
1730 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1731
1732 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001733 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001734 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001735
1736 /* parse substatements */
1737 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1738 switch (child->kw) {
1739 case LY_STMT_DESCRIPTION:
1740 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1741 break;
1742 case LY_STMT_REFERENCE:
1743 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1744 break;
1745 case LY_STMT_EXTENSION_INSTANCE:
1746 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1747 break;
1748 default:
1749 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1750 return LY_EVALID;
1751 }
1752 }
1753
1754 return LY_SUCCESS;
1755}
1756
1757/**
Radek Krejci335332a2019-09-05 13:03:35 +02001758 * @brief Parse the type statement.
1759 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001760 * @param[in] ctx parser context.
1761 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001762 * @param[in,out] type Type to wrote to.
1763 *
1764 * @return LY_ERR values.
1765 */
1766static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001767lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001768{
1769 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001770 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001771 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001772
1773 if (type->name) {
1774 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1775 return LY_EVALID;
1776 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001777
1778 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001779 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001780 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001781
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001782 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1783 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001784 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001785 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001786 type->flags |= LYS_SET_BASE;
1787 break;
1788 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001789 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001790 type->flags |= LYS_SET_BIT;
1791 break;
1792 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001793 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001794 type->flags |= LYS_SET_ENUM;
1795 break;
1796 case LY_STMT_FRACTION_DIGITS:
1797 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1798 type->flags |= LYS_SET_FRDIGITS;
1799 break;
1800 case LY_STMT_LENGTH:
1801 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001802 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001803 return LY_EVALID;
1804 }
1805 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001806 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001807
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001808 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001809 type->flags |= LYS_SET_LENGTH;
1810 break;
1811 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001812 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001813 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001814 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001815 lydict_remove(PARSER_CTX(ctx), str_path);
1816 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001817 type->flags |= LYS_SET_PATH;
1818 break;
1819 case LY_STMT_PATTERN:
1820 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1821 type->flags |= LYS_SET_PATTERN;
1822 break;
1823 case LY_STMT_RANGE:
1824 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001825 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001826 return LY_EVALID;
1827 }
1828 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001829 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001830
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001831 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001832 type->flags |= LYS_SET_RANGE;
1833 break;
1834 case LY_STMT_REQUIRE_INSTANCE:
1835 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001836 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001837 break;
1838 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001839 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001840 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1841 type->flags |= LYS_SET_TYPE;
1842 break;
1843 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001844 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001845 break;
1846 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001847 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001848 return LY_EVALID;
1849 }
1850 }
1851 return LY_SUCCESS;
1852}
1853
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001854/**
1855 * @brief Parse the leaf statement.
1856 *
1857 * @param[in] ctx parser context.
1858 * @param[in] stmt Source statement data from the parsed extension instance.
1859 * @param[in] parent Parent node to connect to (not into).
1860 * @param[in,out] siblings Siblings to add to.
1861 *
1862 * @return LY_ERR values.
1863 */
1864static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001865lysp_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 +01001866{
1867 struct lysp_node_leaf *leaf;
1868
1869 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1870
1871 /* create new leaf structure */
1872 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1873 leaf->nodetype = LYS_LEAF;
1874 leaf->parent = parent;
1875
1876 /* get name */
1877 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1878
1879 /* parse substatements */
1880 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1881 switch (child->kw) {
1882 case LY_STMT_CONFIG:
1883 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1884 break;
1885 case LY_STMT_DEFAULT:
1886 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 +01001887 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001888 break;
1889 case LY_STMT_DESCRIPTION:
1890 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1891 break;
1892 case LY_STMT_IF_FEATURE:
1893 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1894 break;
1895 case LY_STMT_MANDATORY:
1896 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1897 break;
1898 case LY_STMT_MUST:
1899 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1900 break;
1901 case LY_STMT_REFERENCE:
1902 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1903 break;
1904 case LY_STMT_STATUS:
1905 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1906 break;
1907 case LY_STMT_TYPE:
1908 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1909 break;
1910 case LY_STMT_UNITS:
1911 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1912 break;
1913 case LY_STMT_WHEN:
1914 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1915 break;
1916 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001917 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001918 break;
1919 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001920 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001921 return LY_EVALID;
1922 }
1923 }
1924
1925 /* mandatory substatements */
1926 if (!leaf->type.name) {
1927 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1928 return LY_EVALID;
1929 }
1930
1931 return LY_SUCCESS;
1932}
1933
1934/**
1935 * @brief Parse the max-elements statement.
1936 *
1937 * @param[in] ctx parser context.
1938 * @param[in] stmt Source statement data from the parsed extension instance.
1939 * @param[in,out] max Value to write to.
1940 * @param[in,out] flags Flags to write to.
1941 * @param[in,out] exts Extension instances to add to.
1942 *
1943 * @return LY_ERR values.
1944 */
1945static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001946lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
1947 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001948{
1949 size_t arg_len;
1950 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001951 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001952
1953 if (*flags & LYS_SET_MAX) {
1954 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1955 return LY_EVALID;
1956 }
1957 *flags |= LYS_SET_MAX;
1958
1959 /* get value */
1960 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1961 arg_len = strlen(stmt->arg);
1962
1963 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1964 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1965 return LY_EVALID;
1966 }
1967
1968 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1969 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001970 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001971 /* we have not parsed the whole argument */
1972 if ((size_t)(ptr - stmt->arg) != arg_len) {
1973 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1974 return LY_EVALID;
1975 }
1976 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1977 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1978 return LY_EVALID;
1979 }
1980
1981 *max = num;
1982 } else {
1983 /* unbounded */
1984 *max = 0;
1985 }
1986
1987 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1988 switch (child->kw) {
1989 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001990 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001991 break;
1992 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001993 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001994 return LY_EVALID;
1995 }
1996 }
1997
1998 return LY_SUCCESS;
1999}
2000
2001/**
2002 * @brief Parse the min-elements statement.
2003 *
2004 * @param[in] ctx parser context.
2005 * @param[in] stmt Source statement data from the parsed extension instance.
2006 * @param[in,out] min Value to write to.
2007 * @param[in,out] flags Flags to write to.
2008 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002009 * @return LY_ERR values.
2010 */
2011static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002012lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
2013 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002014{
2015 size_t arg_len;
2016 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002017 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002018
2019 if (*flags & LYS_SET_MIN) {
2020 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
2021 return LY_EVALID;
2022 }
2023 *flags |= LYS_SET_MIN;
2024
2025 /* get value */
2026 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2027 arg_len = strlen(stmt->arg);
2028
2029 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
2030 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2031 return LY_EVALID;
2032 }
2033
2034 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002035 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002036 /* we have not parsed the whole argument */
2037 if ((size_t)(ptr - stmt->arg) != arg_len) {
2038 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2039 return LY_EVALID;
2040 }
2041 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2042 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
2043 return LY_EVALID;
2044 }
2045 *min = num;
2046
2047 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2048 switch (child->kw) {
2049 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002050 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002051 break;
2052 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002053 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002054 return LY_EVALID;
2055 }
2056 }
2057
2058 return LY_SUCCESS;
2059}
2060
2061/**
2062 * @brief Parse the ordered-by statement.
2063 *
2064 * @param[in] ctx parser context.
2065 * @param[in] stmt Source statement data from the parsed extension instance.
2066 * @param[in,out] flags Flags to write to.
2067 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002068 * @return LY_ERR values.
2069 */
2070static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002071lysp_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 +01002072{
2073 size_t arg_len;
2074
2075 if (*flags & LYS_ORDBY_MASK) {
2076 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2077 return LY_EVALID;
2078 }
2079
2080 /* get value */
2081 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2082 arg_len = strlen(stmt->arg);
2083 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2084 *flags |= LYS_MAND_TRUE;
2085 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2086 *flags |= LYS_MAND_FALSE;
2087 } else {
2088 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2089 return LY_EVALID;
2090 }
2091
2092 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2093 switch (child->kw) {
2094 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002095 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002096 break;
2097 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002098 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002099 return LY_EVALID;
2100 }
2101 }
2102
2103 return LY_SUCCESS;
2104}
2105
2106/**
2107 * @brief Parse the leaf-list statement.
2108 *
2109 * @param[in] ctx parser context.
2110 * @param[in] stmt Source statement data from the parsed extension instance.
2111 * @param[in] parent Parent node to connect to (not into).
2112 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002113 * @return LY_ERR values.
2114 */
2115static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002116lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002117 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002118{
2119 struct lysp_node_leaflist *llist;
2120
2121 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2122
2123 /* create new leaf-list structure */
2124 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2125 llist->nodetype = LYS_LEAFLIST;
2126 llist->parent = parent;
2127
2128 /* get name */
2129 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2130
2131 /* parse substatements */
2132 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2133 switch (child->kw) {
2134 case LY_STMT_CONFIG:
2135 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2136 break;
2137 case LY_STMT_DEFAULT:
2138 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2139 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2140 break;
2141 case LY_STMT_DESCRIPTION:
2142 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2143 break;
2144 case LY_STMT_IF_FEATURE:
2145 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2146 break;
2147 case LY_STMT_MAX_ELEMENTS:
2148 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2149 break;
2150 case LY_STMT_MIN_ELEMENTS:
2151 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2152 break;
2153 case LY_STMT_MUST:
2154 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2155 break;
2156 case LY_STMT_ORDERED_BY:
2157 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2158 break;
2159 case LY_STMT_REFERENCE:
2160 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2161 break;
2162 case LY_STMT_STATUS:
2163 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2164 break;
2165 case LY_STMT_TYPE:
2166 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2167 break;
2168 case LY_STMT_UNITS:
2169 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2170 break;
2171 case LY_STMT_WHEN:
2172 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2173 break;
2174 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002175 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002176 break;
2177 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002178 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002179 return LY_EVALID;
2180 }
2181 }
2182
2183 /* mandatory substatements */
2184 if (!llist->type.name) {
2185 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2186 return LY_EVALID;
2187 }
2188
2189 return LY_SUCCESS;
2190}
2191
2192/**
2193 * @brief Parse the refine statement.
2194 *
2195 * @param[in] ctx parser context.
2196 * @param[in] stmt Source statement data from the parsed extension instance.
2197 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002198 * @return LY_ERR values.
2199 */
2200static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002201lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002202{
2203 struct lysp_refine *rf;
2204
2205 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2206
2207 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2208
2209 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2210
2211 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2212 switch (child->kw) {
2213 case LY_STMT_CONFIG:
2214 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2215 break;
2216 case LY_STMT_DEFAULT:
2217 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2218 break;
2219 case LY_STMT_DESCRIPTION:
2220 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2221 break;
2222 case LY_STMT_IF_FEATURE:
2223 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2224 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2225 break;
2226 case LY_STMT_MAX_ELEMENTS:
2227 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2228 break;
2229 case LY_STMT_MIN_ELEMENTS:
2230 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2231 break;
2232 case LY_STMT_MUST:
2233 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2234 break;
2235 case LY_STMT_MANDATORY:
2236 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2237 break;
2238 case LY_STMT_REFERENCE:
2239 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2240 break;
2241 case LY_STMT_PRESENCE:
2242 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2243 break;
2244 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002245 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002246 break;
2247 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002248 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002249 return LY_EVALID;
2250 }
2251 }
2252
2253 return LY_SUCCESS;
2254}
2255
2256/**
2257 * @brief Parse the typedef statement.
2258 *
2259 * @param[in] ctx parser context.
2260 * @param[in] stmt Source statement data from the parsed extension instance.
2261 * @param[in] parent Parent node to connect to (not into).
2262 * @param[in,out] typedefs Typedefs to add to.
2263 *
2264 * @return LY_ERR values.
2265 */
2266static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002267lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002268 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002269{
2270 struct lysp_tpdf *tpdf;
2271
2272 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2273
2274 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2275
2276 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2277
2278 /* parse substatements */
2279 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2280 switch (child->kw) {
2281 case LY_STMT_DEFAULT:
2282 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 +01002283 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002284 break;
2285 case LY_STMT_DESCRIPTION:
2286 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2287 break;
2288 case LY_STMT_REFERENCE:
2289 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2290 break;
2291 case LY_STMT_STATUS:
2292 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2293 break;
2294 case LY_STMT_TYPE:
2295 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2296 break;
2297 case LY_STMT_UNITS:
2298 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2299 break;
2300 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002301 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002302 break;
2303 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002304 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002305 return LY_EVALID;
2306 }
2307 }
2308
2309 /* mandatory substatements */
2310 if (!tpdf->type.name) {
2311 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2312 return LY_EVALID;
2313 }
2314
2315 /* store data for collision check */
2316 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2317 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2318 }
2319
2320 return LY_SUCCESS;
2321}
2322
2323/**
2324 * @brief Parse the input or output statement.
2325 *
2326 * @param[in] ctx parser context.
2327 * @param[in] stmt Source statement data from the parsed extension instance.
2328 * @param[in] parent Parent node to connect to (not into).
2329 * @param[in,out] inout_p Input/output pointer to write to.
2330 *
2331 * @return LY_ERR values.
2332 */
2333static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002334lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002335 struct lysp_node_action_inout *inout_p)
2336{
2337 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002338 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002339 return LY_EVALID;
2340 }
2341
2342 /* initiate structure */
2343 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2344 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2345 inout_p->parent = parent;
2346
2347 /* parse substatements */
2348 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2349 switch (child->kw) {
2350 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002351 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002352 /* fall through */
2353 case LY_STMT_ANYXML:
2354 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2355 break;
2356 case LY_STMT_CHOICE:
2357 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2358 break;
2359 case LY_STMT_CONTAINER:
2360 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2361 break;
2362 case LY_STMT_LEAF:
2363 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2364 break;
2365 case LY_STMT_LEAF_LIST:
2366 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2367 break;
2368 case LY_STMT_LIST:
2369 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2370 break;
2371 case LY_STMT_USES:
2372 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2373 break;
2374 case LY_STMT_TYPEDEF:
2375 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2376 break;
2377 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002378 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002379 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2380 break;
2381 case LY_STMT_GROUPING:
2382 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2383 break;
2384 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002385 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002386 break;
2387 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002388 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002389 return LY_EVALID;
2390 }
2391 }
2392
2393 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002394 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002395 return LY_EVALID;
2396 }
2397
2398 return LY_SUCCESS;
2399}
2400
2401/**
2402 * @brief Parse the action statement.
2403 *
2404 * @param[in] ctx parser context.
2405 * @param[in] stmt Source statement data from the parsed extension instance.
2406 * @param[in] parent Parent node to connect to (not into).
2407 * @param[in,out] actions Actions to add to.
2408 *
2409 * @return LY_ERR values.
2410 */
2411static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002412lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002413 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002414{
2415 struct lysp_node_action *act;
2416
2417 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2418
2419 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2420
2421 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2422 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2423 act->parent = parent;
2424
2425 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2426 switch (child->kw) {
2427 case LY_STMT_DESCRIPTION:
2428 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2429 break;
2430 case LY_STMT_IF_FEATURE:
2431 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2432 break;
2433 case LY_STMT_REFERENCE:
2434 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2435 break;
2436 case LY_STMT_STATUS:
2437 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2438 break;
2439
2440 case LY_STMT_INPUT:
2441 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2442 break;
2443 case LY_STMT_OUTPUT:
2444 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2445 break;
2446
2447 case LY_STMT_TYPEDEF:
2448 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2449 break;
2450 case LY_STMT_GROUPING:
2451 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2452 break;
2453 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002454 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 +01002455 break;
2456 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002457 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002458 return LY_EVALID;
2459 }
2460 }
2461
2462 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2463 if (!act->input.nodetype) {
2464 act->input.nodetype = LYS_INPUT;
2465 act->input.parent = &act->node;
2466 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2467 }
2468 if (!act->output.nodetype) {
2469 act->output.nodetype = LYS_OUTPUT;
2470 act->output.parent = &act->node;
2471 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2472 }
2473
2474 return LY_SUCCESS;
2475}
2476
2477/**
2478 * @brief Parse the notification statement.
2479 *
2480 * @param[in] ctx parser context.
2481 * @param[in] stmt Source statement data from the parsed extension instance.
2482 * @param[in] parent Parent node to connect to (not into).
2483 * @param[in,out] notifs Notifications to add to.
2484 *
2485 * @return LY_ERR values.
2486 */
2487static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002488lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002489 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002490{
2491 struct lysp_node_notif *notif;
2492
2493 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2494
2495 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2496
2497 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2498 notif->nodetype = LYS_NOTIF;
2499 notif->parent = parent;
2500
2501 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2502 switch (child->kw) {
2503 case LY_STMT_DESCRIPTION:
2504 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2505 break;
2506 case LY_STMT_IF_FEATURE:
2507 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2508 break;
2509 case LY_STMT_REFERENCE:
2510 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2511 break;
2512 case LY_STMT_STATUS:
2513 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2514 break;
2515
2516 case LY_STMT_ANYDATA:
2517 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2518 /* fall through */
2519 case LY_STMT_ANYXML:
2520 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2521 break;
2522 case LY_STMT_CHOICE:
2523 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2524 break;
2525 case LY_STMT_CONTAINER:
2526 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2527 break;
2528 case LY_STMT_LEAF:
2529 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2530 break;
2531 case LY_STMT_LEAF_LIST:
2532 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2533 break;
2534 case LY_STMT_LIST:
2535 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2536 break;
2537 case LY_STMT_USES:
2538 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2539 break;
2540
2541 case LY_STMT_MUST:
2542 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2543 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2544 break;
2545 case LY_STMT_TYPEDEF:
2546 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2547 break;
2548 case LY_STMT_GROUPING:
2549 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2550 break;
2551 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002552 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002553 break;
2554 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002555 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002556 return LY_EVALID;
2557 }
2558 }
2559
2560 return LY_SUCCESS;
2561}
2562
2563/**
2564 * @brief Parse the grouping statement.
2565 *
2566 * @param[in] ctx parser context.
2567 * @param[in] stmt Source statement data from the parsed extension instance.
2568 * @param[in] parent Parent node to connect to (not into).
2569 * @param[in,out] groupings Groupings to add to.
2570 *
2571 * @return LY_ERR values.
2572 */
2573static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002574lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002575 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002576{
2577 struct lysp_node_grp *grp;
2578
2579 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2580
2581 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2582
2583 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2584 grp->nodetype = LYS_GROUPING;
2585 grp->parent = parent;
2586
2587 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2588 switch (child->kw) {
2589 case LY_STMT_DESCRIPTION:
2590 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2591 break;
2592 case LY_STMT_REFERENCE:
2593 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2594 break;
2595 case LY_STMT_STATUS:
2596 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2597 break;
2598
2599 case LY_STMT_ANYDATA:
2600 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2601 /* fall through */
2602 case LY_STMT_ANYXML:
2603 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2604 break;
2605 case LY_STMT_CHOICE:
2606 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2607 break;
2608 case LY_STMT_CONTAINER:
2609 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2610 break;
2611 case LY_STMT_LEAF:
2612 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2613 break;
2614 case LY_STMT_LEAF_LIST:
2615 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2616 break;
2617 case LY_STMT_LIST:
2618 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2619 break;
2620 case LY_STMT_USES:
2621 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2622 break;
2623
2624 case LY_STMT_TYPEDEF:
2625 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2626 break;
2627 case LY_STMT_ACTION:
2628 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2629 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2630 break;
2631 case LY_STMT_GROUPING:
2632 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2633 break;
2634 case LY_STMT_NOTIFICATION:
2635 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2636 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2637 break;
2638 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002639 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002640 break;
2641 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002642 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002643 return LY_EVALID;
2644 }
2645 }
2646
2647 return LY_SUCCESS;
2648}
2649
2650/**
2651 * @brief Parse the augment statement.
2652 *
2653 * @param[in] ctx parser context.
2654 * @param[in] stmt Source statement data from the parsed extension instance.
2655 * @param[in] parent Parent node to connect to (not into).
2656 * @param[in,out] augments Augments to add to.
2657 *
2658 * @return LY_ERR values.
2659 */
2660static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002661lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002662 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002663{
2664 struct lysp_node_augment *aug;
2665
2666 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2667
2668 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2669
2670 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2671 aug->nodetype = LYS_AUGMENT;
2672 aug->parent = parent;
2673
2674 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2675 switch (child->kw) {
2676 case LY_STMT_DESCRIPTION:
2677 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2678 break;
2679 case LY_STMT_IF_FEATURE:
2680 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2681 break;
2682 case LY_STMT_REFERENCE:
2683 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2684 break;
2685 case LY_STMT_STATUS:
2686 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2687 break;
2688 case LY_STMT_WHEN:
2689 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2690 break;
2691
2692 case LY_STMT_ANYDATA:
2693 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2694 /* fall through */
2695 case LY_STMT_ANYXML:
2696 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2697 break;
2698 case LY_STMT_CASE:
2699 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2700 break;
2701 case LY_STMT_CHOICE:
2702 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2703 break;
2704 case LY_STMT_CONTAINER:
2705 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2706 break;
2707 case LY_STMT_LEAF:
2708 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2709 break;
2710 case LY_STMT_LEAF_LIST:
2711 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2712 break;
2713 case LY_STMT_LIST:
2714 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2715 break;
2716 case LY_STMT_USES:
2717 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2718 break;
2719
2720 case LY_STMT_ACTION:
2721 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2722 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2723 break;
2724 case LY_STMT_NOTIFICATION:
2725 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2726 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2727 break;
2728 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002729 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002730 break;
2731 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002732 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002733 return LY_EVALID;
2734 }
2735 }
2736
2737 return LY_SUCCESS;
2738}
2739
2740/**
2741 * @brief Parse the uses statement.
2742 *
2743 * @param[in] ctx parser context.
2744 * @param[in] stmt Source statement data from the parsed extension instance.
2745 * @param[in] parent Parent node to connect to (not into).
2746 * @param[in,out] siblings Siblings to add to.
2747 *
2748 * @return LY_ERR values.
2749 */
2750static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002751lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002752 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002753{
2754 struct lysp_node_uses *uses;
2755
2756 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2757
2758 /* create uses structure */
2759 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2760
2761 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2762 uses->nodetype = LYS_USES;
2763 uses->parent = parent;
2764
2765 /* parse substatements */
2766 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2767 switch (child->kw) {
2768 case LY_STMT_DESCRIPTION:
2769 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2770 break;
2771 case LY_STMT_IF_FEATURE:
2772 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2773 break;
2774 case LY_STMT_REFERENCE:
2775 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2776 break;
2777 case LY_STMT_STATUS:
2778 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2779 break;
2780 case LY_STMT_WHEN:
2781 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2782 break;
2783
2784 case LY_STMT_REFINE:
2785 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2786 break;
2787 case LY_STMT_AUGMENT:
2788 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2789 break;
2790 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002791 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002792 break;
2793 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002794 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002795 return LY_EVALID;
2796 }
2797 }
2798
2799 return LY_SUCCESS;
2800}
2801
2802/**
2803 * @brief Parse the case statement.
2804 *
2805 * @param[in] ctx parser context.
2806 * @param[in] stmt Source statement data from the parsed extension instance.
2807 * @param[in] parent Parent node to connect to (not into).
2808 * @param[in,out] siblings Siblings to add to.
2809 *
2810 * @return LY_ERR values.
2811 */
2812static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002813lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002814 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002815{
2816 struct lysp_node_case *cas;
2817
2818 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2819
2820 /* create new case structure */
2821 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2822
2823 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2824 cas->nodetype = LYS_CASE;
2825 cas->parent = parent;
2826
2827 /* parse substatements */
2828 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2829 switch (child->kw) {
2830 case LY_STMT_DESCRIPTION:
2831 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2832 break;
2833 case LY_STMT_IF_FEATURE:
2834 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2835 break;
2836 case LY_STMT_REFERENCE:
2837 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2838 break;
2839 case LY_STMT_STATUS:
2840 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2841 break;
2842 case LY_STMT_WHEN:
2843 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2844 break;
2845
2846 case LY_STMT_ANYDATA:
2847 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2848 /* fall through */
2849 case LY_STMT_ANYXML:
2850 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2851 break;
2852 case LY_STMT_CHOICE:
2853 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2854 break;
2855 case LY_STMT_CONTAINER:
2856 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2857 break;
2858 case LY_STMT_LEAF:
2859 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2860 break;
2861 case LY_STMT_LEAF_LIST:
2862 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2863 break;
2864 case LY_STMT_LIST:
2865 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2866 break;
2867 case LY_STMT_USES:
2868 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2869 break;
2870 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002871 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002872 break;
2873 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002874 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002875 return LY_EVALID;
2876 }
2877 }
2878 return LY_SUCCESS;
2879}
2880
2881/**
2882 * @brief Parse the choice statement.
2883 *
2884 * @param[in] ctx parser context.
2885 * @param[in] stmt Source statement data from the parsed extension instance.
2886 * @param[in] parent Parent node to connect to (not into).
2887 * @param[in,out] siblings Siblings to add to.
2888 *
2889 * @return LY_ERR values.
2890 */
2891static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002892lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002893 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002894{
2895 struct lysp_node_choice *choice;
2896
2897 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2898
2899 /* create new choice structure */
2900 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2901
2902 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2903 choice->nodetype = LYS_CHOICE;
2904 choice->parent = parent;
2905
2906 /* parse substatements */
2907 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2908 switch (child->kw) {
2909 case LY_STMT_CONFIG:
2910 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2911 break;
2912 case LY_STMT_DESCRIPTION:
2913 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2914 break;
2915 case LY_STMT_IF_FEATURE:
2916 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2917 break;
2918 case LY_STMT_MANDATORY:
2919 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2920 break;
2921 case LY_STMT_REFERENCE:
2922 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2923 break;
2924 case LY_STMT_STATUS:
2925 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2926 break;
2927 case LY_STMT_WHEN:
2928 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2929 break;
2930 case LY_STMT_DEFAULT:
2931 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 +01002932 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002933 break;
2934 case LY_STMT_ANYDATA:
2935 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2936 /* fall through */
2937 case LY_STMT_ANYXML:
2938 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2939 break;
2940 case LY_STMT_CASE:
2941 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2942 break;
2943 case LY_STMT_CHOICE:
2944 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2945 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2946 break;
2947 case LY_STMT_CONTAINER:
2948 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2949 break;
2950 case LY_STMT_LEAF:
2951 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2952 break;
2953 case LY_STMT_LEAF_LIST:
2954 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2955 break;
2956 case LY_STMT_LIST:
2957 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2958 break;
2959 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002960 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002961 break;
2962 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002963 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002964 return LY_EVALID;
2965 }
2966 }
2967 return LY_SUCCESS;
2968}
2969
2970/**
2971 * @brief Parse the container statement.
2972 *
2973 * @param[in] ctx parser context.
2974 * @param[in] stmt Source statement data from the parsed extension instance.
2975 * @param[in] parent Parent node to connect to (not into).
2976 * @param[in,out] siblings Siblings to add to.
2977 *
2978 * @return LY_ERR values.
2979 */
2980static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002981lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002982 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002983{
2984 struct lysp_node_container *cont;
2985
2986 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2987
2988 /* create new container structure */
2989 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2990
2991 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2992 cont->nodetype = LYS_CONTAINER;
2993 cont->parent = parent;
2994
2995 /* parse substatements */
2996 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2997 switch (child->kw) {
2998 case LY_STMT_CONFIG:
2999 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
3000 break;
3001 case LY_STMT_DESCRIPTION:
3002 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
3003 break;
3004 case LY_STMT_IF_FEATURE:
3005 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
3006 break;
3007 case LY_STMT_REFERENCE:
3008 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
3009 break;
3010 case LY_STMT_STATUS:
3011 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
3012 break;
3013 case LY_STMT_WHEN:
3014 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
3015 break;
3016 case LY_STMT_PRESENCE:
3017 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
3018 break;
3019 case LY_STMT_ANYDATA:
3020 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
3021 /* fall through */
3022 case LY_STMT_ANYXML:
3023 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
3024 break;
3025 case LY_STMT_CHOICE:
3026 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
3027 break;
3028 case LY_STMT_CONTAINER:
3029 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
3030 break;
3031 case LY_STMT_LEAF:
3032 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
3033 break;
3034 case LY_STMT_LEAF_LIST:
3035 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
3036 break;
3037 case LY_STMT_LIST:
3038 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
3039 break;
3040 case LY_STMT_USES:
3041 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
3042 break;
3043
3044 case LY_STMT_TYPEDEF:
3045 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
3046 break;
3047 case LY_STMT_MUST:
3048 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
3049 break;
3050 case LY_STMT_ACTION:
3051 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
3052 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
3053 break;
3054 case LY_STMT_GROUPING:
3055 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3056 break;
3057 case LY_STMT_NOTIFICATION:
3058 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3059 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3060 break;
3061 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003062 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003063 break;
3064 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003065 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003066 return LY_EVALID;
3067 }
3068 }
3069
3070 return LY_SUCCESS;
3071}
3072
3073/**
3074 * @brief Parse the list statement.
3075 *
3076 * @param[in] ctx parser context.
3077 * @param[in] stmt Source statement data from the parsed extension instance.
3078 * @param[in] parent Parent node to connect to (not into).
3079 * @param[in,out] siblings Siblings to add to.
3080 *
3081 * @return LY_ERR values.
3082 */
3083static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003084lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003085 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003086{
3087 struct lysp_node_list *list;
3088
3089 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3090
3091 /* create new list structure */
3092 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3093
3094 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3095 list->nodetype = LYS_LIST;
3096 list->parent = parent;
3097
3098 /* parse substatements */
3099 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3100 switch (child->kw) {
3101 case LY_STMT_CONFIG:
3102 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3103 break;
3104 case LY_STMT_DESCRIPTION:
3105 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3106 break;
3107 case LY_STMT_IF_FEATURE:
3108 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3109 break;
3110 case LY_STMT_REFERENCE:
3111 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3112 break;
3113 case LY_STMT_STATUS:
3114 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3115 break;
3116 case LY_STMT_WHEN:
3117 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3118 break;
3119 case LY_STMT_KEY:
3120 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3121 break;
3122 case LY_STMT_MAX_ELEMENTS:
3123 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3124 break;
3125 case LY_STMT_MIN_ELEMENTS:
3126 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3127 break;
3128 case LY_STMT_ORDERED_BY:
3129 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3130 break;
3131 case LY_STMT_UNIQUE:
3132 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3133 break;
3134
3135 case LY_STMT_ANYDATA:
3136 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3137 /* fall through */
3138 case LY_STMT_ANYXML:
3139 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3140 break;
3141 case LY_STMT_CHOICE:
3142 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3143 break;
3144 case LY_STMT_CONTAINER:
3145 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3146 break;
3147 case LY_STMT_LEAF:
3148 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3149 break;
3150 case LY_STMT_LEAF_LIST:
3151 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3152 break;
3153 case LY_STMT_LIST:
3154 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3155 break;
3156 case LY_STMT_USES:
3157 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3158 break;
3159
3160 case LY_STMT_TYPEDEF:
3161 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3162 break;
3163 case LY_STMT_MUST:
3164 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3165 break;
3166 case LY_STMT_ACTION:
3167 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3168 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3169 break;
3170 case LY_STMT_GROUPING:
3171 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3172 break;
3173 case LY_STMT_NOTIFICATION:
3174 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3175 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3176 break;
3177 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003178 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003179 break;
3180 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003181 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003182 return LY_EVALID;
3183 }
3184 }
3185
3186 return LY_SUCCESS;
3187}
3188
Michal Vasko193dacd2022-10-13 08:43:05 +02003189/**
3190 * @brief Parse generic statement structure into a specific parsed-schema structure.
3191 *
3192 * @param[in] pctx Parse context of the @p stmt being processed.
3193 * @param[in] stmt Generic statement structure to process.
3194 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3195 * @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.
3196 * @return LY_ERR value.
3197 */
3198static LY_ERR
3199lysp_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 +02003200{
Radek Krejciad5963b2019-09-06 16:03:05 +02003201 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003202 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003203
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003204 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003205 case LY_STMT_NOTIFICATION:
3206 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3207 break;
3208 case LY_STMT_INPUT:
3209 case LY_STMT_OUTPUT: {
3210 struct lysp_node_action_inout *inout;
3211
3212 *result = inout = calloc(1, sizeof *inout);
3213 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3214 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3215 break;
3216 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003217 case LY_STMT_ACTION:
3218 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003219 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003220 break;
3221 case LY_STMT_ANYDATA:
3222 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003223 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003224 break;
3225 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003226 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003227 break;
3228 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003229 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003230 break;
3231 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003232 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003233 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003234 case LY_STMT_CONTAINER:
3235 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003236 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003237 case LY_STMT_GROUPING:
3238 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3239 break;
3240 case LY_STMT_LEAF:
3241 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3242 break;
3243 case LY_STMT_LEAF_LIST:
3244 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3245 break;
3246 case LY_STMT_LIST:
3247 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3248 break;
3249 case LY_STMT_USES:
3250 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3251 break;
3252 case LY_STMT_BASE:
3253 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3254 break;
3255 case LY_STMT_ARGUMENT:
3256 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003257 case LY_STMT_CONTACT:
3258 case LY_STMT_DESCRIPTION:
3259 case LY_STMT_ERROR_APP_TAG:
3260 case LY_STMT_ERROR_MESSAGE:
3261 case LY_STMT_KEY:
3262 case LY_STMT_NAMESPACE:
3263 case LY_STMT_ORGANIZATION:
3264 case LY_STMT_PRESENCE:
3265 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003266 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003267 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003268 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003269 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003270 case LY_STMT_BIT:
3271 case LY_STMT_ENUM:
3272 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3273 break;
3274 case LY_STMT_CONFIG:
3275 assert(*result);
3276 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003277 break;
3278 case LY_STMT_DEFAULT:
3279 case LY_STMT_IF_FEATURE:
3280 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003281 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3282 break;
3283 case LY_STMT_DEVIATE:
3284 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3285 break;
3286 case LY_STMT_DEVIATION:
3287 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3288 break;
3289 case LY_STMT_EXTENSION:
3290 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003291 break;
3292 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003293 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3294 break;
3295 case LY_STMT_FEATURE:
3296 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003297 break;
3298 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003299 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003300 break;
3301 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003302 case LY_STMT_RANGE: {
3303 struct lysp_restr *restr;
3304
3305 *result = restr = calloc(1, sizeof *restr);
3306 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3307
3308 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003309 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003310 }
3311 case LY_STMT_MUST:
3312 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3313 break;
3314 case LY_STMT_IDENTITY:
3315 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3316 break;
3317 case LY_STMT_IMPORT:
3318 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3319 break;
3320 case LY_STMT_INCLUDE:
3321 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003322 break;
3323 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003324 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003325 break;
3326 case LY_STMT_MAX_ELEMENTS:
3327 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003328 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003329 break;
3330 case LY_STMT_MIN_ELEMENTS:
3331 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003332 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003333 break;
3334 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003335 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003336 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003337 case LY_STMT_MODULE: {
3338 struct lysp_module *mod;
3339
3340 *result = mod = calloc(1, sizeof *mod);
3341 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3342 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003343 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003344 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003345 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003346 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003347 break;
3348 case LY_STMT_PATH: {
3349 const char *str_path = NULL;
3350
Michal Vasko193dacd2022-10-13 08:43:05 +02003351 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3352 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003353 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003354 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003355 break;
3356 }
3357 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003358 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003359 break;
3360 case LY_STMT_POSITION:
3361 case LY_STMT_VALUE:
3362 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003363 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003364 break;
3365 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003366 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003367 break;
3368 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003369 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003370 break;
3371 case LY_STMT_REQUIRE_INSTANCE:
3372 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003373 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3374 break;
3375 case LY_STMT_REVISION:
3376 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003377 break;
Michal Vasko69730152020-10-09 16:30:07 +02003378 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003379 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003380 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003381 case LY_STMT_SUBMODULE: {
3382 struct lysp_submodule *submod;
3383
3384 *result = submod = calloc(1, sizeof *submod);
3385 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3386 ret = lysp_stmt_submodule(pctx, stmt, submod);
3387 break;
3388 }
Radek Krejci335332a2019-09-05 13:03:35 +02003389 case LY_STMT_TYPE: {
3390 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003391
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003392 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003393 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3394 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003395 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003396 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003397 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003398 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003399 break;
3400 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003401 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3402 break;
3403 case LY_STMT_YANG_VERSION:
3404 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3405 break;
3406 case LY_STMT_YIN_ELEMENT:
3407 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003408 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003409 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003410 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003411 return LY_EINT;
3412 }
3413
Radek Krejciad5963b2019-09-06 16:03:05 +02003414 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003415}
Michal Vasko59892dd2022-05-13 11:02:30 +02003416
Michal Vasko193dacd2022-10-13 08:43:05 +02003417LY_ERR
3418lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003419{
Michal Vasko193dacd2022-10-13 08:43:05 +02003420 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003421
Michal Vasko193dacd2022-10-13 08:43:05 +02003422 if (!substmt->storage) {
3423 /* nothing to parse, ignored */
3424 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003425 }
3426
Michal Vasko193dacd2022-10-13 08:43:05 +02003427 switch (stmt->kw) {
3428 case LY_STMT_NOTIFICATION:
3429 case LY_STMT_INPUT:
3430 case LY_STMT_OUTPUT:
3431 case LY_STMT_ACTION:
3432 case LY_STMT_RPC:
3433 case LY_STMT_ANYDATA:
3434 case LY_STMT_ANYXML:
3435 case LY_STMT_AUGMENT:
3436 case LY_STMT_CASE:
3437 case LY_STMT_CHOICE:
3438 case LY_STMT_CONTAINER:
3439 case LY_STMT_GROUPING:
3440 case LY_STMT_LEAF:
3441 case LY_STMT_LEAF_LIST:
3442 case LY_STMT_LIST:
3443 case LY_STMT_USES: {
3444 struct lysp_node **pnodes_p, *pnode = NULL;
3445
3446 /* parse the node */
3447 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3448
3449 /* usually is a linked-list of all the parsed schema nodes */
3450 pnodes_p = substmt->storage;
3451 while (*pnodes_p) {
3452 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003453 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003454 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003455
3456 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003457 }
3458 case LY_STMT_BASE:
3459 case LY_STMT_BIT:
3460 case LY_STMT_DEFAULT:
3461 case LY_STMT_DEVIATE:
3462 case LY_STMT_DEVIATION:
3463 case LY_STMT_ENUM:
3464 case LY_STMT_EXTENSION:
3465 case LY_STMT_EXTENSION_INSTANCE:
3466 case LY_STMT_FEATURE:
3467 case LY_STMT_IDENTITY:
3468 case LY_STMT_IF_FEATURE:
3469 case LY_STMT_IMPORT:
3470 case LY_STMT_INCLUDE:
3471 case LY_STMT_MUST:
3472 case LY_STMT_PATTERN:
3473 case LY_STMT_REFINE:
3474 case LY_STMT_REVISION:
3475 case LY_STMT_TYPEDEF:
3476 case LY_STMT_UNIQUE:
3477 /* parse, sized array */
3478 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003479 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003480
3481 case LY_STMT_ARGUMENT:
3482 case LY_STMT_BELONGS_TO:
3483 case LY_STMT_CONTACT:
3484 case LY_STMT_DESCRIPTION:
3485 case LY_STMT_ERROR_APP_TAG:
3486 case LY_STMT_ERROR_MESSAGE:
3487 case LY_STMT_FRACTION_DIGITS:
3488 case LY_STMT_KEY:
3489 case LY_STMT_LENGTH:
3490 case LY_STMT_MANDATORY:
3491 case LY_STMT_MAX_ELEMENTS:
3492 case LY_STMT_MIN_ELEMENTS:
3493 case LY_STMT_MODIFIER:
3494 case LY_STMT_MODULE:
3495 case LY_STMT_NAMESPACE:
3496 case LY_STMT_ORGANIZATION:
3497 case LY_STMT_PATH:
3498 case LY_STMT_POSITION:
3499 case LY_STMT_PREFIX:
3500 case LY_STMT_PRESENCE:
3501 case LY_STMT_RANGE:
3502 case LY_STMT_REFERENCE:
3503 case LY_STMT_REQUIRE_INSTANCE:
3504 case LY_STMT_REVISION_DATE:
3505 case LY_STMT_SUBMODULE:
3506 case LY_STMT_TYPE:
3507 case LY_STMT_UNITS:
3508 case LY_STMT_VALUE:
3509 case LY_STMT_WHEN:
3510 case LY_STMT_YANG_VERSION:
3511 case LY_STMT_YIN_ELEMENT:
3512 /* single item */
3513 if (*(void **)substmt->storage) {
3514 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3515 rc = LY_EVALID;
3516 goto cleanup;
3517 }
3518
3519 /* parse */
3520 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003521 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003522
3523 case LY_STMT_CONFIG:
3524 /* single item */
3525 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3526 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3527 rc = LY_EVALID;
3528 goto cleanup;
3529 }
3530
3531 /* parse */
3532 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3533 break;
3534
3535 case LY_STMT_ORDERED_BY:
3536 /* single item */
3537 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3538 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3539 rc = LY_EVALID;
3540 goto cleanup;
3541 }
3542
3543 /* parse */
3544 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3545 break;
3546
3547 case LY_STMT_STATUS:
3548 /* single item */
3549 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3550 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3551 rc = LY_EVALID;
3552 goto cleanup;
3553 }
3554
3555 /* parse */
3556 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3557 break;
3558
Michal Vasko59892dd2022-05-13 11:02:30 +02003559 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003560 LOGINT(PARSER_CTX(pctx));
3561 rc = LY_EINT;
3562 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003563 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003564
3565cleanup:
3566 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003567}