blob: 92b7b292063b93befcac8b8563432055091eec66 [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;
336 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
337 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
338 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
339 lydict_insert(ctx, buf, len, filepath);
340 }
341#else
342 /* get URI if there is /proc */
343 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
344 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
345 lydict_insert(ctx, path, len, filepath);
346 }
347#endif
348 break;
349 case LY_IN_MEMORY:
350 case LY_IN_FILE:
351 /* nothing to do */
352 break;
353 default:
354 LOGINT(ctx);
355 break;
356 }
357}
358
Michal Vaskod0625d72022-10-06 15:02:50 +0200359static 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 +0100360 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200361static 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 +0100362 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200363static 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 +0100364 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200365static 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 +0100366 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200367static 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 +0100368 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200369static 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 +0100370 struct lysp_node **siblings);
371
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100372/**
373 * @brief Validate stmt string value.
374 *
375 * @param[in] ctx Parser context.
376 * @param[in] val_type String value type.
377 * @param[in] val Value to validate.
378 * @return LY_ERR value.
379 */
Radek Krejci335332a2019-09-05 13:03:35 +0200380static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200381lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200382{
Radek Krejci857189e2020-09-01 13:26:36 +0200383 uint8_t prefix = 0;
384 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200385 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200386 size_t utf8_char_len;
387
388 while (*val) {
389 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200390 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200391
392 switch (val_type) {
393 case Y_IDENTIF_ARG:
394 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
395 break;
396 case Y_PREF_IDENTIF_ARG:
397 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
398 break;
399 case Y_STR_ARG:
400 case Y_MAYBE_STR_ARG:
401 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
402 break;
403 }
404 first = 0;
405 }
406
407 return LY_SUCCESS;
408}
409
410/**
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100411 * @brief Duplicate statement siblings, recursively.
412 *
413 * @param[in] ctx Parser context.
414 * @param[in] stmt Statement to duplicate.
415 * @param[out] first First duplicated statement, the rest follow.
416 * @return LY_ERR value.
417 */
418static LY_ERR
419lysp_stmt_dup(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_stmt **first)
420{
421 struct lysp_stmt *child, *last = NULL;
422
423 LY_LIST_FOR(stmt, stmt) {
424 child = calloc(1, sizeof *child);
425 LY_CHECK_ERR_RET(!child, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
426
427 if (last) {
428 last->next = child;
429 } else {
430 assert(!*first);
431 *first = child;
432 }
433 last = child;
434
435 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &child->stmt));
436 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &child->arg));
437 child->format = stmt->format;
438 LY_CHECK_RET(ly_dup_prefix_data(PARSER_CTX(ctx), stmt->format, stmt->prefix_data, &child->prefix_data));
439 child->flags = stmt->flags;
440 child->kw = stmt->kw;
441
442 /* recursively */
443 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &child->child));
444 }
445
446 return LY_SUCCESS;
447}
448
449/**
Radek Krejci335332a2019-09-05 13:03:35 +0200450 * @brief Parse extension instance.
451 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100452 * @param[in] ctx parser context.
453 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100454 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200455 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
456 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200457 * @return LY_ERR values.
458 */
459static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200460lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200461 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200462{
463 struct lysp_ext_instance *e;
464
Michal Vaskob36053d2020-03-26 15:49:30 +0100465 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200466
467 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200468 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100469 e->parent_stmt = insubstmt;
470 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200471 e->parsed = NULL;
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100472 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &e->child));
Radek Krejci335332a2019-09-05 13:03:35 +0200473
474 /* get optional argument */
475 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200476 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200477 }
478
479 return LY_SUCCESS;
480}
481
482/**
483 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
484 * description, etc...
485 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100486 * @param[in] ctx parser context.
487 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200488 * @param[in] substmt_index Index of this substatement.
489 * @param[in,out] value Place to store the parsed value.
490 * @param[in] arg Type of the YANG keyword argument (of the value).
491 * @param[in,out] exts Extension instances to add to.
492 *
493 * @return LY_ERR values.
494 */
495static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200496lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
497 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200498{
Radek Krejci335332a2019-09-05 13:03:35 +0200499 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200500 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200501 return LY_EVALID;
502 }
503
504 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200505 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200506
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100507 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
508 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200509 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100510 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200511 break;
512 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200513 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200514 return LY_EVALID;
515 }
516 }
517 return LY_SUCCESS;
518}
519
520/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200521 * @brief Parse a qname that can have more instances such as if-feature.
522 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100523 * @param[in] ctx parser context.
524 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200525 * @param[in,out] qnames Parsed qnames to add to.
526 * @param[in] arg Type of the expected argument.
527 * @param[in,out] exts Extension instances to add to.
528 *
529 * @return LY_ERR values.
530 */
531static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200532lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
533 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200534{
535 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200536
537 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
538
539 /* allocate new pointer */
540 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
541 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100542 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200543
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100544 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
545 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200546 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100547 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200548 break;
549 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200550 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200551 return LY_EVALID;
552 }
553 }
554 return LY_SUCCESS;
555}
556
557/**
Radek Krejci335332a2019-09-05 13:03:35 +0200558 * @brief Parse a generic text field that can have more instances such as base.
559 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100560 * @param[in] ctx parser context.
561 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200562 * @param[in,out] texts Parsed values to add to.
563 * @param[in] arg Type of the expected argument.
564 * @param[in,out] exts Extension instances to add to.
565 *
566 * @return LY_ERR values.
567 */
568static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200569lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
570 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200571{
572 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200573
574 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
575
576 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100577 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200578 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200579
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100580 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
581 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200582 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100583 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200584 break;
585 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200586 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200587 return LY_EVALID;
588 }
589 }
590 return LY_SUCCESS;
591}
592
593/**
594 * @brief Parse the status statement.
595 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100596 * @param[in] ctx parser context.
597 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200598 * @param[in,out] flags Flags to add to.
599 * @param[in,out] exts Extension instances to add to.
600 *
601 * @return LY_ERR values.
602 */
603static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200604lysp_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 +0200605{
606 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200607
608 if (*flags & LYS_STATUS_MASK) {
609 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
610 return LY_EVALID;
611 }
612
613 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
614 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100615 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200616 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100617 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200618 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100619 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200620 *flags |= LYS_STATUS_OBSLT;
621 } else {
622 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
623 return LY_EVALID;
624 }
625
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100626 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
627 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200628 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100629 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200630 break;
631 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200632 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200633 return LY_EVALID;
634 }
635 }
636 return LY_SUCCESS;
637}
638
639/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100640 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200641 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100642 * @param[in] ctx parser context.
643 * @param[in] stmt Source statement data from the parsed extension instance.
644 * @param[in,out] when_p When pointer to parse to.
645 *
646 * @return LY_ERR values.
647 */
648static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200649lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100650{
651 LY_ERR ret = LY_SUCCESS;
652 struct lysp_when *when;
653
654 if (*when_p) {
655 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
656 return LY_EVALID;
657 }
658
659 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
660
661 when = calloc(1, sizeof *when);
662 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
663 *when_p = when;
664
665 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
666
667 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
668 switch (child->kw) {
669 case LY_STMT_DESCRIPTION:
670 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
671 break;
672 case LY_STMT_REFERENCE:
673 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
674 break;
675 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100676 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100677 break;
678 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200679 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100680 return LY_EVALID;
681 }
682 }
683 return ret;
684}
685
686/**
687 * @brief Parse the config statement.
688 *
689 * @param[in] ctx parser context.
690 * @param[in] stmt Source statement data from the parsed extension instance.
691 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200692 * @param[in,out] exts Extension instances to add to.
693 *
694 * @return LY_ERR values.
695 */
696static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200697lysp_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 +0200698{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100699 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200700
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100701 if (*flags & LYS_CONFIG_MASK) {
702 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
703 return LY_EVALID;
704 }
705
706 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
707 arg_len = strlen(stmt->arg);
708 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
709 *flags |= LYS_CONFIG_W;
710 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
711 *flags |= LYS_CONFIG_R;
712 } else {
713 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
714 return LY_EVALID;
715 }
716
717 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
718 switch (child->kw) {
719 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100720 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100721 break;
722 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200723 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100724 return LY_EVALID;
725 }
726 }
727
728 return LY_SUCCESS;
729}
730
731/**
732 * @brief Parse the mandatory statement.
733 *
734 * @param[in] ctx parser context.
735 * @param[in] stmt Source statement data from the parsed extension instance.
736 * @param[in,out] flags Flags to add to.
737 * @param[in,out] exts Extension instances to add to.
738 *
739 * @return LY_ERR values.
740 */
741static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200742lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200743 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100744{
745 size_t arg_len;
746
747 if (*flags & LYS_MAND_MASK) {
748 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
749 return LY_EVALID;
750 }
751
752 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
753 arg_len = strlen(stmt->arg);
754 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
755 *flags |= LYS_MAND_TRUE;
756 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
757 *flags |= LYS_MAND_FALSE;
758 } else {
759 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
760 return LY_EVALID;
761 }
762
763 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
764 switch (child->kw) {
765 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100766 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100767 break;
768 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200769 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100770 return LY_EVALID;
771 }
772 }
773
774 return LY_SUCCESS;
775}
776
777/**
778 * @brief Parse a restriction such as range or length.
779 *
780 * @param[in] ctx parser context.
781 * @param[in] stmt Source statement data from the parsed extension instance.
782 * @param[in,out] exts Extension instances to add to.
783 *
784 * @return LY_ERR values.
785 */
786static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200787lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100788{
Radek Krejci335332a2019-09-05 13:03:35 +0200789 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200790 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100791 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200792
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100793 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
794 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200795 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100796 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200797 break;
798 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100799 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200800 break;
801 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100802 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200803 break;
804 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100805 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200806 break;
807 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100808 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200809 break;
810 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200811 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200812 return LY_EVALID;
813 }
814 }
815 return LY_SUCCESS;
816}
817
818/**
819 * @brief Parse a restriction that can have more instances such as must.
820 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100821 * @param[in] ctx parser context.
822 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200823 * @param[in,out] restrs Restrictions to add to.
824 *
825 * @return LY_ERR values.
826 */
827static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200828lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200829{
830 struct lysp_restr *restr;
831
Michal Vaskob36053d2020-03-26 15:49:30 +0100832 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100833 return lysp_stmt_restr(ctx, stmt, restr);
834}
835
836/**
837 * @brief Parse the anydata or anyxml statement.
838 *
839 * @param[in] ctx parser context.
840 * @param[in] stmt Source statement data from the parsed extension instance.
841 * @param[in,out] siblings Siblings to add to.
842 *
843 * @return LY_ERR values.
844 */
845static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200846lysp_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 +0100847{
848 struct lysp_node_anydata *any;
849
850 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
851
852 /* create new structure and insert into siblings */
853 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
854
855 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
856 any->parent = parent;
857
858 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
859
860 /* parse substatements */
861 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
862 switch (child->kw) {
863 case LY_STMT_CONFIG:
864 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
865 break;
866 case LY_STMT_DESCRIPTION:
867 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
868 break;
869 case LY_STMT_IF_FEATURE:
870 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
871 break;
872 case LY_STMT_MANDATORY:
873 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
874 break;
875 case LY_STMT_MUST:
876 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
877 break;
878 case LY_STMT_REFERENCE:
879 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
880 break;
881 case LY_STMT_STATUS:
882 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
883 break;
884 case LY_STMT_WHEN:
885 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
886 break;
887 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100888 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100889 break;
890 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200891 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
892 (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 +0100893 return LY_EVALID;
894 }
895 }
896
897 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200898}
899
900/**
901 * @brief Parse the value or position statement. Substatement of type enum statement.
902 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100903 * @param[in] ctx parser context.
904 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200905 * @param[in,out] value Value to write to.
906 * @param[in,out] flags Flags to write to.
907 * @param[in,out] exts Extension instances to add to.
908 *
909 * @return LY_ERR values.
910 */
911static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200912lysp_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 +0200913 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200914{
915 size_t arg_len;
916 char *ptr = NULL;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200917 long long int num = 0;
918 unsigned long long int unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200919
920 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200921 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200922 return LY_EVALID;
923 }
924 *flags |= LYS_SET_VALUE;
925
926 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
927
928 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100929 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
930 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200931 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200932 goto error;
933 }
934
935 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100936 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200937 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200938 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200939 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200940 goto error;
941 }
942 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200943 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200944 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200945 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200946 goto error;
947 }
948 }
949 /* we have not parsed the whole argument */
950 if ((size_t)(ptr - stmt->arg) != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200951 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200952 goto error;
953 }
954 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200955 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200956 goto error;
957 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100958 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200959 *value = num;
960 } else {
961 *value = unum;
962 }
963
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100964 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
965 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200966 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100967 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 +0200968 break;
969 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200970 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200971 return LY_EVALID;
972 }
973 }
974 return LY_SUCCESS;
975
976error:
977 return LY_EVALID;
978}
979
980/**
981 * @brief Parse the enum or bit statement. Substatement of type statement.
982 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100983 * @param[in] ctx parser context.
984 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200985 * @param[in,out] enums Enums or bits to add to.
986 *
987 * @return LY_ERR values.
988 */
989static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200990lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +0200991{
992 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200993
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100994 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 +0200995
Michal Vaskob36053d2020-03-26 15:49:30 +0100996 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200997
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100998 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +0200999 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
1000 } /* else nothing specific for YANG_BIT */
1001
Radek Krejci011e4aa2020-09-04 15:22:31 +02001002 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +02001003 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +02001004
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001005 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1006 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001007 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001008 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001009 break;
1010 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001011 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001012 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001013 break;
1014 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001015 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001016 break;
1017 case LY_STMT_STATUS:
1018 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
1019 break;
1020 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001021 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1022 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001023 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001024 break;
1025 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +02001026 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1027 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001028 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001029 break;
1030 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001031 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001032 break;
1033 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001034 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001035 return LY_EVALID;
1036 }
1037 }
Michal Vasko193dacd2022-10-13 08:43:05 +02001038
Radek Krejci335332a2019-09-05 13:03:35 +02001039 return LY_SUCCESS;
1040}
1041
1042/**
1043 * @brief Parse the fraction-digits statement. Substatement of type statement.
1044 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001045 * @param[in] ctx parser context.
1046 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001047 * @param[in,out] fracdig Value to write to.
1048 * @param[in,out] exts Extension instances to add to.
1049 *
1050 * @return LY_ERR values.
1051 */
1052static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001053lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001054 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001055{
1056 char *ptr;
1057 size_t arg_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001058 unsigned long long int num;
Radek Krejci335332a2019-09-05 13:03:35 +02001059
1060 if (*fracdig) {
1061 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1062 return LY_EVALID;
1063 }
1064
1065 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1066 arg_len = strlen(stmt->arg);
1067 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1068 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1069 return LY_EVALID;
1070 }
1071
1072 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001073 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001074 /* we have not parsed the whole argument */
1075 if ((size_t)(ptr - stmt->arg) != arg_len) {
1076 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1077 return LY_EVALID;
1078 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001079 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001080 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1081 return LY_EVALID;
1082 }
1083 *fracdig = num;
1084
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001085 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1086 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001087 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001088 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001089 break;
1090 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001091 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001092 return LY_EVALID;
1093 }
1094 }
1095 return LY_SUCCESS;
1096}
1097
1098/**
1099 * @brief Parse the require-instance statement. Substatement of type statement.
1100 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001101 * @param[in] ctx parser context.
1102 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001103 * @param[in,out] reqinst Value to write to.
1104 * @param[in,out] flags Flags to write to.
1105 * @param[in,out] exts Extension instances to add to.
1106 *
1107 * @return LY_ERR values.
1108 */
1109static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001110lysp_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 +02001111 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001112{
1113 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001114
1115 if (*flags & LYS_SET_REQINST) {
1116 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1117 return LY_EVALID;
1118 }
1119 *flags |= LYS_SET_REQINST;
1120
1121 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1122 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001123 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001124 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001125 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001126 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1127 return LY_EVALID;
1128 }
1129
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001130 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1131 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001132 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001133 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001134 break;
1135 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001136 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001137 return LY_EVALID;
1138 }
1139 }
1140 return LY_SUCCESS;
1141}
1142
1143/**
1144 * @brief Parse the modifier statement. Substatement of type pattern statement.
1145 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001146 * @param[in] ctx parser context.
1147 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001148 * @param[in,out] pat Value to write to.
1149 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001150 * @return LY_ERR values.
1151 */
1152static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001153lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001154 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001155{
1156 size_t arg_len;
1157 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001158
Radek Krejcif13b87b2020-12-01 22:02:17 +01001159 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001160 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1161 return LY_EVALID;
1162 }
1163
1164 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1165 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001166 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001167 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1168 return LY_EVALID;
1169 }
1170
1171 /* replace the value in the dictionary */
1172 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001173 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001174 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001175 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001176
Radek Krejcif13b87b2020-12-01 22:02:17 +01001177 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1178 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001179 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001180
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001181 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1182 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001183 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001184 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001185 break;
1186 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001187 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001188 return LY_EVALID;
1189 }
1190 }
1191 return LY_SUCCESS;
1192}
1193
1194/**
1195 * @brief Parse the pattern statement. Substatement of type statement.
1196 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001197 * @param[in] ctx parser context.
1198 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001199 * @param[in,out] patterns Restrictions to add to.
1200 *
1201 * @return LY_ERR values.
1202 */
1203static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001204lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001205{
1206 char *buf;
1207 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001208 struct lysp_restr *restr;
1209
1210 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001211 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001212 arg_len = strlen(stmt->arg);
1213
1214 /* add special meaning first byte */
1215 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001216 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001217 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001218 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001219 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001220 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001221 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001222
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001223 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1224 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001225 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001226 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001227 break;
1228 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001229 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001230 break;
1231 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001232 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001233 break;
1234 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001235 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001236 break;
1237 case LY_STMT_MODIFIER:
1238 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001239 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001240 break;
1241 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001242 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001243 break;
1244 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001245 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001246 return LY_EVALID;
1247 }
1248 }
1249 return LY_SUCCESS;
1250}
1251
1252/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001253 * @brief Parse the deviate statement. Substatement of deviation statement.
1254 *
1255 * @param[in] ctx parser context.
1256 * @param[in] stmt Source statement data from the parsed extension instance.
1257 * @param[in,out] devs Array of deviates to add to.
1258 * @param[in,out] exts Extension instances to add to.
1259 * @return LY_ERR values.
1260 */
1261static LY_ERR
1262lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1263{
1264 (void)stmt;
1265 (void)devs;
1266 (void)exts;
1267
1268 /* TODO */
1269 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1270 return LY_EINVAL;
1271}
1272
1273/**
1274 * @brief Parse the deviation statement.
1275 *
1276 * @param[in] ctx parser context.
1277 * @param[in] stmt Source statement data from the parsed extension instance.
1278 * @param[in,out] deviations Array of deviations to add to.
1279 * @return LY_ERR values.
1280 */
1281static LY_ERR
1282lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1283{
1284 struct lysp_deviation *dev;
1285
1286 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1287
1288 /* store nodeid */
1289 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1290 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1291
1292 /* parse substatements */
1293 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1294 switch (child->kw) {
1295 case LY_STMT_DESCRIPTION:
1296 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1297 break;
1298 case LY_STMT_DEVIATE:
1299 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1300 break;
1301 case LY_STMT_REFERENCE:
1302 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1303 break;
1304 case LY_STMT_EXTENSION_INSTANCE:
1305 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1306 break;
1307 default:
1308 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1309 return LY_EVALID;
1310 }
1311 }
1312
1313 return LY_SUCCESS;
1314}
1315
1316/**
1317 * @brief Parse the yang-version statement.
1318 *
1319 * @param[in] ctx parser context.
1320 * @param[in] stmt Source statement data from the parsed extension instance.
1321 * @param[out] version Version to write to.
1322 * @param[in,out] exts Extension instances to add to.
1323 * @return LY_ERR values.
1324 */
1325static LY_ERR
1326lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1327{
1328 if (*version) {
1329 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1330 return LY_EVALID;
1331 }
1332
1333 /* store flag */
1334 if (!strcmp(stmt->arg, "1")) {
1335 *version = LYS_VERSION_1_0;
1336 } else if (!strcmp(stmt->arg, "1.1")) {
1337 *version = LYS_VERSION_1_1;
1338 } else {
1339 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yang-version");
1340 return LY_EVALID;
1341 }
1342
1343 /* parse substatements */
1344 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1345 switch (child->kw) {
1346 case LY_STMT_EXTENSION_INSTANCE:
1347 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1348 break;
1349 default:
1350 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1351 return LY_EVALID;
1352 }
1353 }
1354
1355 return LY_SUCCESS;
1356}
1357
1358/**
1359 * @brief Parse the module statement.
1360 *
1361 * @param[in] ctx parser context.
1362 * @param[in] stmt Source statement data from the parsed extension instance.
1363 * @param[in,out] mod Module to fill.
1364 * @return LY_ERR values.
1365 */
1366static LY_ERR
1367lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1368{
1369 (void)stmt;
1370 (void)mod;
1371
1372 /* TODO */
1373 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1374 return LY_EINVAL;
1375}
1376
1377/**
1378 * @brief Parse the submodule statement.
1379 *
1380 * @param[in] ctx parser context.
1381 * @param[in] stmt Source statement data from the parsed extension instance.
1382 * @param[in,out] submod Module to fill.
1383 * @return LY_ERR values.
1384 */
1385static LY_ERR
1386lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1387{
1388 (void)stmt;
1389 (void)submod;
1390
1391 /* TODO */
1392 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1393 return LY_EINVAL;
1394}
1395
1396/**
1397 * @brief Parse the yin-element statement. Substatement of argument statement.
1398 *
1399 * @param[in] ctx parser context.
1400 * @param[in] stmt Source statement data from the parsed extension instance.
1401 * @param[in,out] flags Flags to write to.
1402 * @param[in,out] exts Extension instances to add to.
1403 * @return LY_ERR values.
1404 */
1405static LY_ERR
1406lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1407{
1408 if (*flags & LYS_YINELEM_MASK) {
1409 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1410 return LY_EVALID;
1411 }
1412
1413 /* store flag */
1414 if (!strcmp(stmt->arg, "true")) {
1415 *flags |= LYS_YINELEM_TRUE;
1416 } else if (!strcmp(stmt->arg, "false")) {
1417 *flags |= LYS_YINELEM_FALSE;
1418 } else {
1419 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yin-element");
1420 return LY_EVALID;
1421 }
1422
1423 /* parse substatements */
1424 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1425 switch (child->kw) {
1426 case LY_STMT_EXTENSION_INSTANCE:
1427 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1428 break;
1429 default:
1430 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1431 return LY_EVALID;
1432 }
1433 }
1434
1435 return LY_SUCCESS;
1436}
1437
1438/**
1439 * @brief Parse the argument statement. Substatement of extension statement.
1440 *
1441 * @param[in] ctx parser context.
1442 * @param[in] stmt Source statement data from the parsed extension instance.
1443 * @param[in,out] ex Extension to fill.
1444 * @return LY_ERR values.
1445 */
1446static LY_ERR
1447lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1448{
1449 if (ex->argname) {
1450 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1451 return LY_EVALID;
1452 }
1453
1454 /* store argument name */
1455 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1456 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1457
1458 /* parse substatements */
1459 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1460 switch (child->kw) {
1461 case LY_STMT_YIN_ELEMENT:
1462 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1463 break;
1464 case LY_STMT_EXTENSION_INSTANCE:
1465 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1466 break;
1467 default:
1468 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1469 return LY_EVALID;
1470 }
1471 }
1472
1473 return LY_SUCCESS;
1474}
1475
1476/**
1477 * @brief Parse the extension statement.
1478 *
1479 * @param[in] ctx parser context.
1480 * @param[in] stmt Source statement data from the parsed extension instance.
1481 * @param[in,out] extensions Array of extensions to add to.
1482 * @return LY_ERR values.
1483 */
1484static LY_ERR
1485lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1486{
1487 struct lysp_ext *ex;
1488
1489 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1490
1491 /* store name */
1492 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1493 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1494
1495 /* parse substatements */
1496 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1497 switch (child->kw) {
1498 case LY_STMT_DESCRIPTION:
1499 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1500 break;
1501 case LY_STMT_REFERENCE:
1502 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1503 break;
1504 case LY_STMT_STATUS:
1505 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1506 break;
1507 case LY_STMT_ARGUMENT:
1508 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1509 break;
1510 case LY_STMT_EXTENSION_INSTANCE:
1511 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1512 break;
1513 default:
1514 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1515 return LY_EVALID;
1516 }
1517 }
1518
1519 return LY_SUCCESS;
1520}
1521
1522/**
1523 * @brief Parse the feature statement.
1524 *
1525 * @param[in] ctx parser context.
1526 * @param[in] stmt Source statement data from the parsed extension instance.
1527 * @param[in,out] features Array of features to add to.
1528 * @return LY_ERR values.
1529 */
1530static LY_ERR
1531lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1532{
1533 struct lysp_feature *feat;
1534
1535 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1536
1537 /* store name */
1538 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1539 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1540
1541 /* parse substatements */
1542 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1543 switch (child->kw) {
1544 case LY_STMT_DESCRIPTION:
1545 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1546 break;
1547 case LY_STMT_IF_FEATURE:
1548 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1549 break;
1550 case LY_STMT_REFERENCE:
1551 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1552 break;
1553 case LY_STMT_STATUS:
1554 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1555 break;
1556 case LY_STMT_EXTENSION_INSTANCE:
1557 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1558 break;
1559 default:
1560 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1561 return LY_EVALID;
1562 }
1563 }
1564
1565 return LY_SUCCESS;
1566}
1567
1568/**
1569 * @brief Parse the identity statement.
1570 *
1571 * @param[in] ctx parser context.
1572 * @param[in] stmt Source statement data from the parsed extension instance.
1573 * @param[in,out] identities Array of identities to add to.
1574 * @return LY_ERR values.
1575 */
1576static LY_ERR
1577lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1578{
1579 struct lysp_ident *ident;
1580
1581 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1582
1583 /* store name */
1584 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1585 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1586
1587 /* parse substatements */
1588 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1589 switch (child->kw) {
1590 case LY_STMT_DESCRIPTION:
1591 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1592 break;
1593 case LY_STMT_IF_FEATURE:
1594 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1595 break;
1596 case LY_STMT_REFERENCE:
1597 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1598 break;
1599 case LY_STMT_STATUS:
1600 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1601 break;
1602 case LY_STMT_BASE:
1603 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1604 break;
1605 case LY_STMT_EXTENSION_INSTANCE:
1606 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1607 break;
1608 default:
1609 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1610 return LY_EVALID;
1611 }
1612 }
1613
1614 return LY_SUCCESS;
1615}
1616
1617/**
1618 * @brief Parse the import statement.
1619 *
1620 * @param[in] ctx parser context.
1621 * @param[in] stmt Source statement data from the parsed extension instance.
1622 * @param[in,out] imports Array of imports to add to.
1623 * @return LY_ERR values.
1624 */
1625static LY_ERR
1626lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1627{
1628 struct lysp_import *imp;
1629 const char *str = NULL;
1630
1631 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1632
1633 /* store name */
1634 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1635 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1636
1637 /* parse substatements */
1638 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1639 switch (child->kw) {
1640 case LY_STMT_PREFIX:
1641 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1642 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1643 break;
1644 case LY_STMT_DESCRIPTION:
1645 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1646 break;
1647 case LY_STMT_REFERENCE:
1648 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1649 break;
1650 case LY_STMT_REVISION_DATE:
1651 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1652 strcpy(imp->rev, str);
1653 lydict_remove(PARSER_CTX(ctx), str);
1654 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1655 break;
1656 case LY_STMT_EXTENSION_INSTANCE:
1657 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1658 break;
1659 default:
1660 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1661 return LY_EVALID;
1662 }
1663 }
1664
1665 return LY_SUCCESS;
1666}
1667
1668/**
1669 * @brief Parse the include statement.
1670 *
1671 * @param[in] ctx parser context.
1672 * @param[in] stmt Source statement data from the parsed extension instance.
1673 * @param[in,out] includes Array of identities to add to.
1674 * @return LY_ERR values.
1675 */
1676static LY_ERR
1677lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1678{
1679 struct lysp_include *inc;
1680 const char *str = NULL;
1681
1682 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1683
1684 /* store name */
1685 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1686 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1687
1688 /* parse substatements */
1689 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1690 switch (child->kw) {
1691 case LY_STMT_DESCRIPTION:
1692 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1693 break;
1694 case LY_STMT_REFERENCE:
1695 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1696 break;
1697 case LY_STMT_REVISION_DATE:
1698 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1699 strcpy(inc->rev, str);
1700 lydict_remove(PARSER_CTX(ctx), str);
1701 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1702 break;
1703 case LY_STMT_EXTENSION_INSTANCE:
1704 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1705 break;
1706 default:
1707 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1708 return LY_EVALID;
1709 }
1710 }
1711
1712 return LY_SUCCESS;
1713}
1714
1715/**
1716 * @brief Parse the revision statement.
1717 *
1718 * @param[in] ctx parser context.
1719 * @param[in] stmt Source statement data from the parsed extension instance.
1720 * @param[in,out] includes Array of identities to add to.
1721 * @return LY_ERR values.
1722 */
1723static LY_ERR
1724lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1725{
1726 struct lysp_revision *rev;
1727
1728 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1729
1730 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001731 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001732 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001733
1734 /* parse substatements */
1735 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1736 switch (child->kw) {
1737 case LY_STMT_DESCRIPTION:
1738 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1739 break;
1740 case LY_STMT_REFERENCE:
1741 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1742 break;
1743 case LY_STMT_EXTENSION_INSTANCE:
1744 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1745 break;
1746 default:
1747 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1748 return LY_EVALID;
1749 }
1750 }
1751
1752 return LY_SUCCESS;
1753}
1754
1755/**
Radek Krejci335332a2019-09-05 13:03:35 +02001756 * @brief Parse the type statement.
1757 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001758 * @param[in] ctx parser context.
1759 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001760 * @param[in,out] type Type to wrote to.
1761 *
1762 * @return LY_ERR values.
1763 */
1764static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001765lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001766{
1767 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001768 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001769 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001770
1771 if (type->name) {
1772 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1773 return LY_EVALID;
1774 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001775
1776 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001777 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001778 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001779
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001780 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1781 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001782 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001783 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001784 type->flags |= LYS_SET_BASE;
1785 break;
1786 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001787 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001788 type->flags |= LYS_SET_BIT;
1789 break;
1790 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001791 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001792 type->flags |= LYS_SET_ENUM;
1793 break;
1794 case LY_STMT_FRACTION_DIGITS:
1795 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1796 type->flags |= LYS_SET_FRDIGITS;
1797 break;
1798 case LY_STMT_LENGTH:
1799 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001800 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001801 return LY_EVALID;
1802 }
1803 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001804 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001805
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001806 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001807 type->flags |= LYS_SET_LENGTH;
1808 break;
1809 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001810 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001811 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001812 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001813 lydict_remove(PARSER_CTX(ctx), str_path);
1814 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001815 type->flags |= LYS_SET_PATH;
1816 break;
1817 case LY_STMT_PATTERN:
1818 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1819 type->flags |= LYS_SET_PATTERN;
1820 break;
1821 case LY_STMT_RANGE:
1822 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001823 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001824 return LY_EVALID;
1825 }
1826 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001827 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001828
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001829 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001830 type->flags |= LYS_SET_RANGE;
1831 break;
1832 case LY_STMT_REQUIRE_INSTANCE:
1833 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001834 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001835 break;
1836 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001837 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001838 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1839 type->flags |= LYS_SET_TYPE;
1840 break;
1841 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001842 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001843 break;
1844 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001845 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001846 return LY_EVALID;
1847 }
1848 }
1849 return LY_SUCCESS;
1850}
1851
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001852/**
1853 * @brief Parse the leaf statement.
1854 *
1855 * @param[in] ctx parser context.
1856 * @param[in] stmt Source statement data from the parsed extension instance.
1857 * @param[in] parent Parent node to connect to (not into).
1858 * @param[in,out] siblings Siblings to add to.
1859 *
1860 * @return LY_ERR values.
1861 */
1862static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001863lysp_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 +01001864{
1865 struct lysp_node_leaf *leaf;
1866
1867 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1868
1869 /* create new leaf structure */
1870 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1871 leaf->nodetype = LYS_LEAF;
1872 leaf->parent = parent;
1873
1874 /* get name */
1875 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1876
1877 /* parse substatements */
1878 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1879 switch (child->kw) {
1880 case LY_STMT_CONFIG:
1881 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1882 break;
1883 case LY_STMT_DEFAULT:
1884 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 +01001885 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001886 break;
1887 case LY_STMT_DESCRIPTION:
1888 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1889 break;
1890 case LY_STMT_IF_FEATURE:
1891 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1892 break;
1893 case LY_STMT_MANDATORY:
1894 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1895 break;
1896 case LY_STMT_MUST:
1897 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1898 break;
1899 case LY_STMT_REFERENCE:
1900 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1901 break;
1902 case LY_STMT_STATUS:
1903 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1904 break;
1905 case LY_STMT_TYPE:
1906 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1907 break;
1908 case LY_STMT_UNITS:
1909 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1910 break;
1911 case LY_STMT_WHEN:
1912 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1913 break;
1914 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001915 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001916 break;
1917 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001918 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001919 return LY_EVALID;
1920 }
1921 }
1922
1923 /* mandatory substatements */
1924 if (!leaf->type.name) {
1925 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1926 return LY_EVALID;
1927 }
1928
1929 return LY_SUCCESS;
1930}
1931
1932/**
1933 * @brief Parse the max-elements statement.
1934 *
1935 * @param[in] ctx parser context.
1936 * @param[in] stmt Source statement data from the parsed extension instance.
1937 * @param[in,out] max Value to write to.
1938 * @param[in,out] flags Flags to write to.
1939 * @param[in,out] exts Extension instances to add to.
1940 *
1941 * @return LY_ERR values.
1942 */
1943static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001944lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
1945 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001946{
1947 size_t arg_len;
1948 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001949 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001950
1951 if (*flags & LYS_SET_MAX) {
1952 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1953 return LY_EVALID;
1954 }
1955 *flags |= LYS_SET_MAX;
1956
1957 /* get value */
1958 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1959 arg_len = strlen(stmt->arg);
1960
1961 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1962 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1963 return LY_EVALID;
1964 }
1965
1966 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1967 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001968 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001969 /* we have not parsed the whole argument */
1970 if ((size_t)(ptr - stmt->arg) != arg_len) {
1971 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1972 return LY_EVALID;
1973 }
1974 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1975 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1976 return LY_EVALID;
1977 }
1978
1979 *max = num;
1980 } else {
1981 /* unbounded */
1982 *max = 0;
1983 }
1984
1985 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1986 switch (child->kw) {
1987 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001988 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001989 break;
1990 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001991 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001992 return LY_EVALID;
1993 }
1994 }
1995
1996 return LY_SUCCESS;
1997}
1998
1999/**
2000 * @brief Parse the min-elements statement.
2001 *
2002 * @param[in] ctx parser context.
2003 * @param[in] stmt Source statement data from the parsed extension instance.
2004 * @param[in,out] min Value to write to.
2005 * @param[in,out] flags Flags to write to.
2006 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002007 * @return LY_ERR values.
2008 */
2009static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002010lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
2011 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002012{
2013 size_t arg_len;
2014 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002015 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002016
2017 if (*flags & LYS_SET_MIN) {
2018 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
2019 return LY_EVALID;
2020 }
2021 *flags |= LYS_SET_MIN;
2022
2023 /* get value */
2024 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2025 arg_len = strlen(stmt->arg);
2026
2027 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
2028 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2029 return LY_EVALID;
2030 }
2031
2032 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002033 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002034 /* we have not parsed the whole argument */
2035 if ((size_t)(ptr - stmt->arg) != arg_len) {
2036 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2037 return LY_EVALID;
2038 }
2039 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2040 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
2041 return LY_EVALID;
2042 }
2043 *min = num;
2044
2045 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2046 switch (child->kw) {
2047 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002048 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002049 break;
2050 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002051 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002052 return LY_EVALID;
2053 }
2054 }
2055
2056 return LY_SUCCESS;
2057}
2058
2059/**
2060 * @brief Parse the ordered-by statement.
2061 *
2062 * @param[in] ctx parser context.
2063 * @param[in] stmt Source statement data from the parsed extension instance.
2064 * @param[in,out] flags Flags to write to.
2065 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002066 * @return LY_ERR values.
2067 */
2068static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002069lysp_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 +01002070{
2071 size_t arg_len;
2072
2073 if (*flags & LYS_ORDBY_MASK) {
2074 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2075 return LY_EVALID;
2076 }
2077
2078 /* get value */
2079 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2080 arg_len = strlen(stmt->arg);
2081 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2082 *flags |= LYS_MAND_TRUE;
2083 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2084 *flags |= LYS_MAND_FALSE;
2085 } else {
2086 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2087 return LY_EVALID;
2088 }
2089
2090 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2091 switch (child->kw) {
2092 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002093 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002094 break;
2095 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002096 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002097 return LY_EVALID;
2098 }
2099 }
2100
2101 return LY_SUCCESS;
2102}
2103
2104/**
2105 * @brief Parse the leaf-list statement.
2106 *
2107 * @param[in] ctx parser context.
2108 * @param[in] stmt Source statement data from the parsed extension instance.
2109 * @param[in] parent Parent node to connect to (not into).
2110 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002111 * @return LY_ERR values.
2112 */
2113static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002114lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002115 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002116{
2117 struct lysp_node_leaflist *llist;
2118
2119 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2120
2121 /* create new leaf-list structure */
2122 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2123 llist->nodetype = LYS_LEAFLIST;
2124 llist->parent = parent;
2125
2126 /* get name */
2127 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2128
2129 /* parse substatements */
2130 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2131 switch (child->kw) {
2132 case LY_STMT_CONFIG:
2133 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2134 break;
2135 case LY_STMT_DEFAULT:
2136 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2137 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2138 break;
2139 case LY_STMT_DESCRIPTION:
2140 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2141 break;
2142 case LY_STMT_IF_FEATURE:
2143 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2144 break;
2145 case LY_STMT_MAX_ELEMENTS:
2146 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2147 break;
2148 case LY_STMT_MIN_ELEMENTS:
2149 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2150 break;
2151 case LY_STMT_MUST:
2152 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2153 break;
2154 case LY_STMT_ORDERED_BY:
2155 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2156 break;
2157 case LY_STMT_REFERENCE:
2158 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2159 break;
2160 case LY_STMT_STATUS:
2161 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2162 break;
2163 case LY_STMT_TYPE:
2164 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2165 break;
2166 case LY_STMT_UNITS:
2167 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2168 break;
2169 case LY_STMT_WHEN:
2170 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2171 break;
2172 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002173 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002174 break;
2175 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002176 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002177 return LY_EVALID;
2178 }
2179 }
2180
2181 /* mandatory substatements */
2182 if (!llist->type.name) {
2183 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2184 return LY_EVALID;
2185 }
2186
2187 return LY_SUCCESS;
2188}
2189
2190/**
2191 * @brief Parse the refine statement.
2192 *
2193 * @param[in] ctx parser context.
2194 * @param[in] stmt Source statement data from the parsed extension instance.
2195 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002196 * @return LY_ERR values.
2197 */
2198static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002199lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002200{
2201 struct lysp_refine *rf;
2202
2203 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2204
2205 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2206
2207 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2208
2209 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2210 switch (child->kw) {
2211 case LY_STMT_CONFIG:
2212 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2213 break;
2214 case LY_STMT_DEFAULT:
2215 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2216 break;
2217 case LY_STMT_DESCRIPTION:
2218 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2219 break;
2220 case LY_STMT_IF_FEATURE:
2221 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2222 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2223 break;
2224 case LY_STMT_MAX_ELEMENTS:
2225 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2226 break;
2227 case LY_STMT_MIN_ELEMENTS:
2228 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2229 break;
2230 case LY_STMT_MUST:
2231 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2232 break;
2233 case LY_STMT_MANDATORY:
2234 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2235 break;
2236 case LY_STMT_REFERENCE:
2237 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2238 break;
2239 case LY_STMT_PRESENCE:
2240 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2241 break;
2242 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002243 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002244 break;
2245 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002246 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002247 return LY_EVALID;
2248 }
2249 }
2250
2251 return LY_SUCCESS;
2252}
2253
2254/**
2255 * @brief Parse the typedef statement.
2256 *
2257 * @param[in] ctx parser context.
2258 * @param[in] stmt Source statement data from the parsed extension instance.
2259 * @param[in] parent Parent node to connect to (not into).
2260 * @param[in,out] typedefs Typedefs to add to.
2261 *
2262 * @return LY_ERR values.
2263 */
2264static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002265lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002266 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002267{
2268 struct lysp_tpdf *tpdf;
2269
2270 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2271
2272 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2273
2274 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2275
2276 /* parse substatements */
2277 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2278 switch (child->kw) {
2279 case LY_STMT_DEFAULT:
2280 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 +01002281 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002282 break;
2283 case LY_STMT_DESCRIPTION:
2284 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2285 break;
2286 case LY_STMT_REFERENCE:
2287 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2288 break;
2289 case LY_STMT_STATUS:
2290 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2291 break;
2292 case LY_STMT_TYPE:
2293 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2294 break;
2295 case LY_STMT_UNITS:
2296 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2297 break;
2298 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002299 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002300 break;
2301 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002302 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002303 return LY_EVALID;
2304 }
2305 }
2306
2307 /* mandatory substatements */
2308 if (!tpdf->type.name) {
2309 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2310 return LY_EVALID;
2311 }
2312
2313 /* store data for collision check */
2314 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2315 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2316 }
2317
2318 return LY_SUCCESS;
2319}
2320
2321/**
2322 * @brief Parse the input or output statement.
2323 *
2324 * @param[in] ctx parser context.
2325 * @param[in] stmt Source statement data from the parsed extension instance.
2326 * @param[in] parent Parent node to connect to (not into).
2327 * @param[in,out] inout_p Input/output pointer to write to.
2328 *
2329 * @return LY_ERR values.
2330 */
2331static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002332lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002333 struct lysp_node_action_inout *inout_p)
2334{
2335 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002336 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002337 return LY_EVALID;
2338 }
2339
2340 /* initiate structure */
2341 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2342 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2343 inout_p->parent = parent;
2344
2345 /* parse substatements */
2346 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2347 switch (child->kw) {
2348 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002349 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002350 /* fall through */
2351 case LY_STMT_ANYXML:
2352 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2353 break;
2354 case LY_STMT_CHOICE:
2355 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2356 break;
2357 case LY_STMT_CONTAINER:
2358 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2359 break;
2360 case LY_STMT_LEAF:
2361 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2362 break;
2363 case LY_STMT_LEAF_LIST:
2364 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2365 break;
2366 case LY_STMT_LIST:
2367 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2368 break;
2369 case LY_STMT_USES:
2370 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2371 break;
2372 case LY_STMT_TYPEDEF:
2373 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2374 break;
2375 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002376 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002377 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2378 break;
2379 case LY_STMT_GROUPING:
2380 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2381 break;
2382 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002383 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002384 break;
2385 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002386 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002387 return LY_EVALID;
2388 }
2389 }
2390
2391 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002392 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002393 return LY_EVALID;
2394 }
2395
2396 return LY_SUCCESS;
2397}
2398
2399/**
2400 * @brief Parse the action statement.
2401 *
2402 * @param[in] ctx parser context.
2403 * @param[in] stmt Source statement data from the parsed extension instance.
2404 * @param[in] parent Parent node to connect to (not into).
2405 * @param[in,out] actions Actions to add to.
2406 *
2407 * @return LY_ERR values.
2408 */
2409static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002410lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002411 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002412{
2413 struct lysp_node_action *act;
2414
2415 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2416
2417 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2418
2419 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2420 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2421 act->parent = parent;
2422
2423 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2424 switch (child->kw) {
2425 case LY_STMT_DESCRIPTION:
2426 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2427 break;
2428 case LY_STMT_IF_FEATURE:
2429 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2430 break;
2431 case LY_STMT_REFERENCE:
2432 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2433 break;
2434 case LY_STMT_STATUS:
2435 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2436 break;
2437
2438 case LY_STMT_INPUT:
2439 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2440 break;
2441 case LY_STMT_OUTPUT:
2442 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2443 break;
2444
2445 case LY_STMT_TYPEDEF:
2446 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2447 break;
2448 case LY_STMT_GROUPING:
2449 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2450 break;
2451 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002452 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 +01002453 break;
2454 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002455 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002456 return LY_EVALID;
2457 }
2458 }
2459
2460 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2461 if (!act->input.nodetype) {
2462 act->input.nodetype = LYS_INPUT;
2463 act->input.parent = &act->node;
2464 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2465 }
2466 if (!act->output.nodetype) {
2467 act->output.nodetype = LYS_OUTPUT;
2468 act->output.parent = &act->node;
2469 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2470 }
2471
2472 return LY_SUCCESS;
2473}
2474
2475/**
2476 * @brief Parse the notification statement.
2477 *
2478 * @param[in] ctx parser context.
2479 * @param[in] stmt Source statement data from the parsed extension instance.
2480 * @param[in] parent Parent node to connect to (not into).
2481 * @param[in,out] notifs Notifications to add to.
2482 *
2483 * @return LY_ERR values.
2484 */
2485static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002486lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002487 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002488{
2489 struct lysp_node_notif *notif;
2490
2491 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2492
2493 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2494
2495 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2496 notif->nodetype = LYS_NOTIF;
2497 notif->parent = parent;
2498
2499 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2500 switch (child->kw) {
2501 case LY_STMT_DESCRIPTION:
2502 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2503 break;
2504 case LY_STMT_IF_FEATURE:
2505 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2506 break;
2507 case LY_STMT_REFERENCE:
2508 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2509 break;
2510 case LY_STMT_STATUS:
2511 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2512 break;
2513
2514 case LY_STMT_ANYDATA:
2515 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2516 /* fall through */
2517 case LY_STMT_ANYXML:
2518 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2519 break;
2520 case LY_STMT_CHOICE:
2521 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2522 break;
2523 case LY_STMT_CONTAINER:
2524 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2525 break;
2526 case LY_STMT_LEAF:
2527 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2528 break;
2529 case LY_STMT_LEAF_LIST:
2530 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2531 break;
2532 case LY_STMT_LIST:
2533 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2534 break;
2535 case LY_STMT_USES:
2536 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2537 break;
2538
2539 case LY_STMT_MUST:
2540 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2541 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2542 break;
2543 case LY_STMT_TYPEDEF:
2544 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2545 break;
2546 case LY_STMT_GROUPING:
2547 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2548 break;
2549 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002550 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002551 break;
2552 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002553 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002554 return LY_EVALID;
2555 }
2556 }
2557
2558 return LY_SUCCESS;
2559}
2560
2561/**
2562 * @brief Parse the grouping statement.
2563 *
2564 * @param[in] ctx parser context.
2565 * @param[in] stmt Source statement data from the parsed extension instance.
2566 * @param[in] parent Parent node to connect to (not into).
2567 * @param[in,out] groupings Groupings to add to.
2568 *
2569 * @return LY_ERR values.
2570 */
2571static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002572lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002573 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002574{
2575 struct lysp_node_grp *grp;
2576
2577 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2578
2579 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2580
2581 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2582 grp->nodetype = LYS_GROUPING;
2583 grp->parent = parent;
2584
2585 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2586 switch (child->kw) {
2587 case LY_STMT_DESCRIPTION:
2588 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2589 break;
2590 case LY_STMT_REFERENCE:
2591 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2592 break;
2593 case LY_STMT_STATUS:
2594 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2595 break;
2596
2597 case LY_STMT_ANYDATA:
2598 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2599 /* fall through */
2600 case LY_STMT_ANYXML:
2601 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2602 break;
2603 case LY_STMT_CHOICE:
2604 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2605 break;
2606 case LY_STMT_CONTAINER:
2607 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2608 break;
2609 case LY_STMT_LEAF:
2610 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2611 break;
2612 case LY_STMT_LEAF_LIST:
2613 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2614 break;
2615 case LY_STMT_LIST:
2616 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2617 break;
2618 case LY_STMT_USES:
2619 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2620 break;
2621
2622 case LY_STMT_TYPEDEF:
2623 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2624 break;
2625 case LY_STMT_ACTION:
2626 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2627 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2628 break;
2629 case LY_STMT_GROUPING:
2630 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2631 break;
2632 case LY_STMT_NOTIFICATION:
2633 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2634 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2635 break;
2636 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002637 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002638 break;
2639 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002640 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002641 return LY_EVALID;
2642 }
2643 }
2644
2645 return LY_SUCCESS;
2646}
2647
2648/**
2649 * @brief Parse the augment statement.
2650 *
2651 * @param[in] ctx parser context.
2652 * @param[in] stmt Source statement data from the parsed extension instance.
2653 * @param[in] parent Parent node to connect to (not into).
2654 * @param[in,out] augments Augments to add to.
2655 *
2656 * @return LY_ERR values.
2657 */
2658static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002659lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002660 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002661{
2662 struct lysp_node_augment *aug;
2663
2664 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2665
2666 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2667
2668 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2669 aug->nodetype = LYS_AUGMENT;
2670 aug->parent = parent;
2671
2672 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2673 switch (child->kw) {
2674 case LY_STMT_DESCRIPTION:
2675 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2676 break;
2677 case LY_STMT_IF_FEATURE:
2678 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2679 break;
2680 case LY_STMT_REFERENCE:
2681 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2682 break;
2683 case LY_STMT_STATUS:
2684 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2685 break;
2686 case LY_STMT_WHEN:
2687 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2688 break;
2689
2690 case LY_STMT_ANYDATA:
2691 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2692 /* fall through */
2693 case LY_STMT_ANYXML:
2694 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2695 break;
2696 case LY_STMT_CASE:
2697 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2698 break;
2699 case LY_STMT_CHOICE:
2700 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2701 break;
2702 case LY_STMT_CONTAINER:
2703 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2704 break;
2705 case LY_STMT_LEAF:
2706 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2707 break;
2708 case LY_STMT_LEAF_LIST:
2709 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2710 break;
2711 case LY_STMT_LIST:
2712 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2713 break;
2714 case LY_STMT_USES:
2715 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2716 break;
2717
2718 case LY_STMT_ACTION:
2719 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2720 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2721 break;
2722 case LY_STMT_NOTIFICATION:
2723 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2724 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2725 break;
2726 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002727 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002728 break;
2729 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002730 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002731 return LY_EVALID;
2732 }
2733 }
2734
2735 return LY_SUCCESS;
2736}
2737
2738/**
2739 * @brief Parse the uses statement.
2740 *
2741 * @param[in] ctx parser context.
2742 * @param[in] stmt Source statement data from the parsed extension instance.
2743 * @param[in] parent Parent node to connect to (not into).
2744 * @param[in,out] siblings Siblings to add to.
2745 *
2746 * @return LY_ERR values.
2747 */
2748static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002749lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002750 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002751{
2752 struct lysp_node_uses *uses;
2753
2754 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2755
2756 /* create uses structure */
2757 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2758
2759 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2760 uses->nodetype = LYS_USES;
2761 uses->parent = parent;
2762
2763 /* parse substatements */
2764 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2765 switch (child->kw) {
2766 case LY_STMT_DESCRIPTION:
2767 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2768 break;
2769 case LY_STMT_IF_FEATURE:
2770 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2771 break;
2772 case LY_STMT_REFERENCE:
2773 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2774 break;
2775 case LY_STMT_STATUS:
2776 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2777 break;
2778 case LY_STMT_WHEN:
2779 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2780 break;
2781
2782 case LY_STMT_REFINE:
2783 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2784 break;
2785 case LY_STMT_AUGMENT:
2786 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2787 break;
2788 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002789 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002790 break;
2791 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002792 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002793 return LY_EVALID;
2794 }
2795 }
2796
2797 return LY_SUCCESS;
2798}
2799
2800/**
2801 * @brief Parse the case statement.
2802 *
2803 * @param[in] ctx parser context.
2804 * @param[in] stmt Source statement data from the parsed extension instance.
2805 * @param[in] parent Parent node to connect to (not into).
2806 * @param[in,out] siblings Siblings to add to.
2807 *
2808 * @return LY_ERR values.
2809 */
2810static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002811lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002812 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002813{
2814 struct lysp_node_case *cas;
2815
2816 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2817
2818 /* create new case structure */
2819 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2820
2821 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2822 cas->nodetype = LYS_CASE;
2823 cas->parent = parent;
2824
2825 /* parse substatements */
2826 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2827 switch (child->kw) {
2828 case LY_STMT_DESCRIPTION:
2829 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2830 break;
2831 case LY_STMT_IF_FEATURE:
2832 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2833 break;
2834 case LY_STMT_REFERENCE:
2835 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2836 break;
2837 case LY_STMT_STATUS:
2838 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2839 break;
2840 case LY_STMT_WHEN:
2841 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2842 break;
2843
2844 case LY_STMT_ANYDATA:
2845 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2846 /* fall through */
2847 case LY_STMT_ANYXML:
2848 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2849 break;
2850 case LY_STMT_CHOICE:
2851 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2852 break;
2853 case LY_STMT_CONTAINER:
2854 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2855 break;
2856 case LY_STMT_LEAF:
2857 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2858 break;
2859 case LY_STMT_LEAF_LIST:
2860 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2861 break;
2862 case LY_STMT_LIST:
2863 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2864 break;
2865 case LY_STMT_USES:
2866 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2867 break;
2868 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002869 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002870 break;
2871 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002872 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002873 return LY_EVALID;
2874 }
2875 }
2876 return LY_SUCCESS;
2877}
2878
2879/**
2880 * @brief Parse the choice statement.
2881 *
2882 * @param[in] ctx parser context.
2883 * @param[in] stmt Source statement data from the parsed extension instance.
2884 * @param[in] parent Parent node to connect to (not into).
2885 * @param[in,out] siblings Siblings to add to.
2886 *
2887 * @return LY_ERR values.
2888 */
2889static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002890lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002891 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002892{
2893 struct lysp_node_choice *choice;
2894
2895 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2896
2897 /* create new choice structure */
2898 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2899
2900 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2901 choice->nodetype = LYS_CHOICE;
2902 choice->parent = parent;
2903
2904 /* parse substatements */
2905 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2906 switch (child->kw) {
2907 case LY_STMT_CONFIG:
2908 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2909 break;
2910 case LY_STMT_DESCRIPTION:
2911 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2912 break;
2913 case LY_STMT_IF_FEATURE:
2914 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2915 break;
2916 case LY_STMT_MANDATORY:
2917 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2918 break;
2919 case LY_STMT_REFERENCE:
2920 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2921 break;
2922 case LY_STMT_STATUS:
2923 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2924 break;
2925 case LY_STMT_WHEN:
2926 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2927 break;
2928 case LY_STMT_DEFAULT:
2929 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 +01002930 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002931 break;
2932 case LY_STMT_ANYDATA:
2933 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2934 /* fall through */
2935 case LY_STMT_ANYXML:
2936 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2937 break;
2938 case LY_STMT_CASE:
2939 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2940 break;
2941 case LY_STMT_CHOICE:
2942 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2943 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2944 break;
2945 case LY_STMT_CONTAINER:
2946 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2947 break;
2948 case LY_STMT_LEAF:
2949 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2950 break;
2951 case LY_STMT_LEAF_LIST:
2952 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2953 break;
2954 case LY_STMT_LIST:
2955 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2956 break;
2957 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002958 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002959 break;
2960 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002961 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002962 return LY_EVALID;
2963 }
2964 }
2965 return LY_SUCCESS;
2966}
2967
2968/**
2969 * @brief Parse the container statement.
2970 *
2971 * @param[in] ctx parser context.
2972 * @param[in] stmt Source statement data from the parsed extension instance.
2973 * @param[in] parent Parent node to connect to (not into).
2974 * @param[in,out] siblings Siblings to add to.
2975 *
2976 * @return LY_ERR values.
2977 */
2978static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002979lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002980 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002981{
2982 struct lysp_node_container *cont;
2983
2984 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2985
2986 /* create new container structure */
2987 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2988
2989 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2990 cont->nodetype = LYS_CONTAINER;
2991 cont->parent = parent;
2992
2993 /* parse substatements */
2994 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2995 switch (child->kw) {
2996 case LY_STMT_CONFIG:
2997 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
2998 break;
2999 case LY_STMT_DESCRIPTION:
3000 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
3001 break;
3002 case LY_STMT_IF_FEATURE:
3003 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
3004 break;
3005 case LY_STMT_REFERENCE:
3006 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
3007 break;
3008 case LY_STMT_STATUS:
3009 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
3010 break;
3011 case LY_STMT_WHEN:
3012 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
3013 break;
3014 case LY_STMT_PRESENCE:
3015 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
3016 break;
3017 case LY_STMT_ANYDATA:
3018 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
3019 /* fall through */
3020 case LY_STMT_ANYXML:
3021 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
3022 break;
3023 case LY_STMT_CHOICE:
3024 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
3025 break;
3026 case LY_STMT_CONTAINER:
3027 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
3028 break;
3029 case LY_STMT_LEAF:
3030 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
3031 break;
3032 case LY_STMT_LEAF_LIST:
3033 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
3034 break;
3035 case LY_STMT_LIST:
3036 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
3037 break;
3038 case LY_STMT_USES:
3039 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
3040 break;
3041
3042 case LY_STMT_TYPEDEF:
3043 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
3044 break;
3045 case LY_STMT_MUST:
3046 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
3047 break;
3048 case LY_STMT_ACTION:
3049 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
3050 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
3051 break;
3052 case LY_STMT_GROUPING:
3053 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3054 break;
3055 case LY_STMT_NOTIFICATION:
3056 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3057 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3058 break;
3059 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003060 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003061 break;
3062 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003063 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003064 return LY_EVALID;
3065 }
3066 }
3067
3068 return LY_SUCCESS;
3069}
3070
3071/**
3072 * @brief Parse the list statement.
3073 *
3074 * @param[in] ctx parser context.
3075 * @param[in] stmt Source statement data from the parsed extension instance.
3076 * @param[in] parent Parent node to connect to (not into).
3077 * @param[in,out] siblings Siblings to add to.
3078 *
3079 * @return LY_ERR values.
3080 */
3081static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003082lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003083 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003084{
3085 struct lysp_node_list *list;
3086
3087 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3088
3089 /* create new list structure */
3090 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3091
3092 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3093 list->nodetype = LYS_LIST;
3094 list->parent = parent;
3095
3096 /* parse substatements */
3097 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3098 switch (child->kw) {
3099 case LY_STMT_CONFIG:
3100 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3101 break;
3102 case LY_STMT_DESCRIPTION:
3103 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3104 break;
3105 case LY_STMT_IF_FEATURE:
3106 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3107 break;
3108 case LY_STMT_REFERENCE:
3109 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3110 break;
3111 case LY_STMT_STATUS:
3112 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3113 break;
3114 case LY_STMT_WHEN:
3115 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3116 break;
3117 case LY_STMT_KEY:
3118 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3119 break;
3120 case LY_STMT_MAX_ELEMENTS:
3121 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3122 break;
3123 case LY_STMT_MIN_ELEMENTS:
3124 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3125 break;
3126 case LY_STMT_ORDERED_BY:
3127 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3128 break;
3129 case LY_STMT_UNIQUE:
3130 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3131 break;
3132
3133 case LY_STMT_ANYDATA:
3134 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3135 /* fall through */
3136 case LY_STMT_ANYXML:
3137 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3138 break;
3139 case LY_STMT_CHOICE:
3140 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3141 break;
3142 case LY_STMT_CONTAINER:
3143 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3144 break;
3145 case LY_STMT_LEAF:
3146 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3147 break;
3148 case LY_STMT_LEAF_LIST:
3149 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3150 break;
3151 case LY_STMT_LIST:
3152 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3153 break;
3154 case LY_STMT_USES:
3155 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3156 break;
3157
3158 case LY_STMT_TYPEDEF:
3159 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3160 break;
3161 case LY_STMT_MUST:
3162 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3163 break;
3164 case LY_STMT_ACTION:
3165 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3166 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3167 break;
3168 case LY_STMT_GROUPING:
3169 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3170 break;
3171 case LY_STMT_NOTIFICATION:
3172 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3173 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3174 break;
3175 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003176 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003177 break;
3178 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003179 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003180 return LY_EVALID;
3181 }
3182 }
3183
3184 return LY_SUCCESS;
3185}
3186
Michal Vasko193dacd2022-10-13 08:43:05 +02003187/**
3188 * @brief Parse generic statement structure into a specific parsed-schema structure.
3189 *
3190 * @param[in] pctx Parse context of the @p stmt being processed.
3191 * @param[in] stmt Generic statement structure to process.
3192 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3193 * @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.
3194 * @return LY_ERR value.
3195 */
3196static LY_ERR
3197lysp_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 +02003198{
Radek Krejciad5963b2019-09-06 16:03:05 +02003199 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003200 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003201
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003202 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003203 case LY_STMT_NOTIFICATION:
3204 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3205 break;
3206 case LY_STMT_INPUT:
3207 case LY_STMT_OUTPUT: {
3208 struct lysp_node_action_inout *inout;
3209
3210 *result = inout = calloc(1, sizeof *inout);
3211 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3212 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3213 break;
3214 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003215 case LY_STMT_ACTION:
3216 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003217 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003218 break;
3219 case LY_STMT_ANYDATA:
3220 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003221 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003222 break;
3223 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003224 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003225 break;
3226 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003227 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003228 break;
3229 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003230 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003231 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003232 case LY_STMT_CONTAINER:
3233 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003234 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003235 case LY_STMT_GROUPING:
3236 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3237 break;
3238 case LY_STMT_LEAF:
3239 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3240 break;
3241 case LY_STMT_LEAF_LIST:
3242 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3243 break;
3244 case LY_STMT_LIST:
3245 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3246 break;
3247 case LY_STMT_USES:
3248 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3249 break;
3250 case LY_STMT_BASE:
3251 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3252 break;
3253 case LY_STMT_ARGUMENT:
3254 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003255 case LY_STMT_CONTACT:
3256 case LY_STMT_DESCRIPTION:
3257 case LY_STMT_ERROR_APP_TAG:
3258 case LY_STMT_ERROR_MESSAGE:
3259 case LY_STMT_KEY:
3260 case LY_STMT_NAMESPACE:
3261 case LY_STMT_ORGANIZATION:
3262 case LY_STMT_PRESENCE:
3263 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003264 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003265 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003266 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003267 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003268 case LY_STMT_BIT:
3269 case LY_STMT_ENUM:
3270 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3271 break;
3272 case LY_STMT_CONFIG:
3273 assert(*result);
3274 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003275 break;
3276 case LY_STMT_DEFAULT:
3277 case LY_STMT_IF_FEATURE:
3278 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003279 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3280 break;
3281 case LY_STMT_DEVIATE:
3282 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3283 break;
3284 case LY_STMT_DEVIATION:
3285 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3286 break;
3287 case LY_STMT_EXTENSION:
3288 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003289 break;
3290 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003291 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3292 break;
3293 case LY_STMT_FEATURE:
3294 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003295 break;
3296 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003297 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003298 break;
3299 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003300 case LY_STMT_RANGE: {
3301 struct lysp_restr *restr;
3302
3303 *result = restr = calloc(1, sizeof *restr);
3304 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3305
3306 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003307 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003308 }
3309 case LY_STMT_MUST:
3310 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3311 break;
3312 case LY_STMT_IDENTITY:
3313 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3314 break;
3315 case LY_STMT_IMPORT:
3316 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3317 break;
3318 case LY_STMT_INCLUDE:
3319 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003320 break;
3321 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003322 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003323 break;
3324 case LY_STMT_MAX_ELEMENTS:
3325 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003326 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003327 break;
3328 case LY_STMT_MIN_ELEMENTS:
3329 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003330 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003331 break;
3332 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003333 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003334 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003335 case LY_STMT_MODULE: {
3336 struct lysp_module *mod;
3337
3338 *result = mod = calloc(1, sizeof *mod);
3339 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3340 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003341 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003342 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003343 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003344 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003345 break;
3346 case LY_STMT_PATH: {
3347 const char *str_path = NULL;
3348
Michal Vasko193dacd2022-10-13 08:43:05 +02003349 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3350 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003351 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003352 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003353 break;
3354 }
3355 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003356 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003357 break;
3358 case LY_STMT_POSITION:
3359 case LY_STMT_VALUE:
3360 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003361 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003362 break;
3363 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003364 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003365 break;
3366 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003367 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003368 break;
3369 case LY_STMT_REQUIRE_INSTANCE:
3370 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003371 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3372 break;
3373 case LY_STMT_REVISION:
3374 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003375 break;
Michal Vasko69730152020-10-09 16:30:07 +02003376 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003377 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003378 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003379 case LY_STMT_SUBMODULE: {
3380 struct lysp_submodule *submod;
3381
3382 *result = submod = calloc(1, sizeof *submod);
3383 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3384 ret = lysp_stmt_submodule(pctx, stmt, submod);
3385 break;
3386 }
Radek Krejci335332a2019-09-05 13:03:35 +02003387 case LY_STMT_TYPE: {
3388 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003389
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003390 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003391 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3392 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003393 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003394 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003395 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003396 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003397 break;
3398 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003399 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3400 break;
3401 case LY_STMT_YANG_VERSION:
3402 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3403 break;
3404 case LY_STMT_YIN_ELEMENT:
3405 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003406 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003407 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003408 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003409 return LY_EINT;
3410 }
3411
Radek Krejciad5963b2019-09-06 16:03:05 +02003412 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003413}
Michal Vasko59892dd2022-05-13 11:02:30 +02003414
Michal Vasko193dacd2022-10-13 08:43:05 +02003415LY_ERR
3416lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003417{
Michal Vasko193dacd2022-10-13 08:43:05 +02003418 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003419
Michal Vasko193dacd2022-10-13 08:43:05 +02003420 if (!substmt->storage) {
3421 /* nothing to parse, ignored */
3422 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003423 }
3424
Michal Vasko193dacd2022-10-13 08:43:05 +02003425 switch (stmt->kw) {
3426 case LY_STMT_NOTIFICATION:
3427 case LY_STMT_INPUT:
3428 case LY_STMT_OUTPUT:
3429 case LY_STMT_ACTION:
3430 case LY_STMT_RPC:
3431 case LY_STMT_ANYDATA:
3432 case LY_STMT_ANYXML:
3433 case LY_STMT_AUGMENT:
3434 case LY_STMT_CASE:
3435 case LY_STMT_CHOICE:
3436 case LY_STMT_CONTAINER:
3437 case LY_STMT_GROUPING:
3438 case LY_STMT_LEAF:
3439 case LY_STMT_LEAF_LIST:
3440 case LY_STMT_LIST:
3441 case LY_STMT_USES: {
3442 struct lysp_node **pnodes_p, *pnode = NULL;
3443
3444 /* parse the node */
3445 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3446
3447 /* usually is a linked-list of all the parsed schema nodes */
3448 pnodes_p = substmt->storage;
3449 while (*pnodes_p) {
3450 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003451 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003452 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003453
3454 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003455 }
3456 case LY_STMT_BASE:
3457 case LY_STMT_BIT:
3458 case LY_STMT_DEFAULT:
3459 case LY_STMT_DEVIATE:
3460 case LY_STMT_DEVIATION:
3461 case LY_STMT_ENUM:
3462 case LY_STMT_EXTENSION:
3463 case LY_STMT_EXTENSION_INSTANCE:
3464 case LY_STMT_FEATURE:
3465 case LY_STMT_IDENTITY:
3466 case LY_STMT_IF_FEATURE:
3467 case LY_STMT_IMPORT:
3468 case LY_STMT_INCLUDE:
3469 case LY_STMT_MUST:
3470 case LY_STMT_PATTERN:
3471 case LY_STMT_REFINE:
3472 case LY_STMT_REVISION:
3473 case LY_STMT_TYPEDEF:
3474 case LY_STMT_UNIQUE:
3475 /* parse, sized array */
3476 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003477 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003478
3479 case LY_STMT_ARGUMENT:
3480 case LY_STMT_BELONGS_TO:
3481 case LY_STMT_CONTACT:
3482 case LY_STMT_DESCRIPTION:
3483 case LY_STMT_ERROR_APP_TAG:
3484 case LY_STMT_ERROR_MESSAGE:
3485 case LY_STMT_FRACTION_DIGITS:
3486 case LY_STMT_KEY:
3487 case LY_STMT_LENGTH:
3488 case LY_STMT_MANDATORY:
3489 case LY_STMT_MAX_ELEMENTS:
3490 case LY_STMT_MIN_ELEMENTS:
3491 case LY_STMT_MODIFIER:
3492 case LY_STMT_MODULE:
3493 case LY_STMT_NAMESPACE:
3494 case LY_STMT_ORGANIZATION:
3495 case LY_STMT_PATH:
3496 case LY_STMT_POSITION:
3497 case LY_STMT_PREFIX:
3498 case LY_STMT_PRESENCE:
3499 case LY_STMT_RANGE:
3500 case LY_STMT_REFERENCE:
3501 case LY_STMT_REQUIRE_INSTANCE:
3502 case LY_STMT_REVISION_DATE:
3503 case LY_STMT_SUBMODULE:
3504 case LY_STMT_TYPE:
3505 case LY_STMT_UNITS:
3506 case LY_STMT_VALUE:
3507 case LY_STMT_WHEN:
3508 case LY_STMT_YANG_VERSION:
3509 case LY_STMT_YIN_ELEMENT:
3510 /* single item */
3511 if (*(void **)substmt->storage) {
3512 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3513 rc = LY_EVALID;
3514 goto cleanup;
3515 }
3516
3517 /* parse */
3518 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003519 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003520
3521 case LY_STMT_CONFIG:
3522 /* single item */
3523 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3524 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3525 rc = LY_EVALID;
3526 goto cleanup;
3527 }
3528
3529 /* parse */
3530 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3531 break;
3532
3533 case LY_STMT_ORDERED_BY:
3534 /* single item */
3535 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3536 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3537 rc = LY_EVALID;
3538 goto cleanup;
3539 }
3540
3541 /* parse */
3542 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3543 break;
3544
3545 case LY_STMT_STATUS:
3546 /* single item */
3547 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3548 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3549 rc = LY_EVALID;
3550 goto cleanup;
3551 }
3552
3553 /* parse */
3554 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3555 break;
3556
Michal Vasko59892dd2022-05-13 11:02:30 +02003557 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003558 LOGINT(PARSER_CTX(pctx));
3559 rc = LY_EINT;
3560 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003561 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003562
3563cleanup:
3564 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003565}