blob: 809ed863dd5d85b18b979a5d9d40a5def6962141 [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
91 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
92 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
93 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
94 return LY_EINVAL;
95 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
96 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
97 iter->schema->name);
98 return LY_EINVAL;
99 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
100 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
101 iter->schema->name);
102 return LY_EINVAL;
103 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
104 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
105 iter->schema->name);
106 return LY_EINVAL;
107 }
108
109 *op = (struct lyd_node *)iter;
110 return LY_SUCCESS;
111}
112
113LY_ERR
114lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
115{
116 LY_ERR rc = LY_SUCCESS;
117
118 LOG_LOCSET(snode, NULL, NULL, NULL);
119
120 if (lydctx->int_opts & LYD_INTOPT_ANY) {
121 /* nothing to check, everything is allowed */
122 goto cleanup;
123 }
124
125 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
126 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
127 rc = LY_EVALID;
128 goto cleanup;
129 }
130
131 if (snode->nodetype == LYS_RPC) {
132 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
133 if (lydctx->op_node) {
134 goto error_node_dup;
135 }
136 } else {
137 goto error_node_inval;
138 }
139 } else if (snode->nodetype == LYS_ACTION) {
140 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
141 if (lydctx->op_node) {
142 goto error_node_dup;
143 }
144 } else {
145 goto error_node_inval;
146 }
147 } else if (snode->nodetype == LYS_NOTIF) {
148 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
149 if (lydctx->op_node) {
150 goto error_node_dup;
151 }
152 } else {
153 goto error_node_inval;
154 }
155 }
156
157 /* success */
158 goto cleanup;
159
160error_node_dup:
161 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
162 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
163 lydctx->op_node->schema->name);
164 rc = LY_EVALID;
165 goto cleanup;
166
167error_node_inval:
168 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
169 snode->name);
170 rc = LY_EVALID;
171
172cleanup:
173 LOG_LOCBACK(1, 0, 0, 0);
174 return rc;
175}
176
177LY_ERR
178lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
179 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
180{
181 ly_bool incomplete;
182
183 LY_CHECK_RET(lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node));
184
185 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
186 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
187 }
188 return LY_SUCCESS;
189}
190
191LY_ERR
192lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
193 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
194 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
195{
196 ly_bool incomplete;
197 struct lyd_meta *first = NULL;
198
199 if (meta && *meta) {
200 /* remember the first metadata */
201 first = *meta;
202 }
203
204 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
205 hints, ctx_node, 0, &incomplete));
206
207 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
208 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
209 }
210
211 if (first) {
212 /* always return the first metadata */
213 *meta = first;
214 }
215
216 return LY_SUCCESS;
217}
218
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200219LY_ERR
220lyd_parse_check_keys(struct lyd_node *node)
221{
222 const struct lysc_node *skey = NULL;
223 const struct lyd_node *key;
224
225 assert(node->schema->nodetype == LYS_LIST);
226
227 key = lyd_child(node);
228 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
229 if (!key || (key->schema != skey)) {
230 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
231 return LY_EVALID;
232 }
233
234 key = key->next;
235 }
236
237 return LY_SUCCESS;
238}
239
240LY_ERR
241lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
242 struct lysc_ext_instance *ext)
243{
244 struct lyd_meta *meta2, *prev_meta = NULL;
245 struct lyd_ctx_ext_val *ext_val;
246
247 if (lysc_has_when(node->schema)) {
248 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
249 /* remember we need to evaluate this node's when */
250 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
251 }
252 }
253
254 LY_LIST_FOR(*meta, meta2) {
255 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
256 meta2->value.boolean) {
257 /* node is default according to the metadata */
258 node->flags |= LYD_DEFAULT;
259
260 /* delete the metadata */
261 if (prev_meta) {
262 prev_meta->next = meta2->next;
263 } else {
264 *meta = (*meta)->next;
265 }
266 lyd_free_meta_single(meta2);
267 break;
268 }
269
270 prev_meta = meta2;
271 }
272
273 if (ext) {
274 /* parsed for an extension */
275 node->flags |= LYD_EXT;
276
277 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
278 /* rememeber for validation */
279 ext_val = malloc(sizeof *ext_val);
280 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
281 ext_val->ext = ext;
282 ext_val->sibling = node;
283 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
284 }
285 }
286
287 return LY_SUCCESS;
288}
289
Michal Vasko193dacd2022-10-13 08:43:05 +0200290void
291lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
292{
293 char path[PATH_MAX];
294
295#ifndef __APPLE__
296 char proc_path[32];
297 int len;
298#endif
299
300 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
301 if (*filepath) {
302 /* filepath already set */
303 return;
304 }
305
306 switch (in->type) {
307 case LY_IN_FILEPATH:
308 if (realpath(in->method.fpath.filepath, path) != NULL) {
309 lydict_insert(ctx, path, 0, filepath);
310 } else {
311 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
312 }
313
314 break;
315 case LY_IN_FD:
316#ifdef __APPLE__
317 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
318 lydict_insert(ctx, path, 0, filepath);
319 }
320#elif defined _WIN32
321 HANDLE h = _get_osfhandle(in->method.fd);
322 FILE_NAME_INFO info;
323 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
324 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
325 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
326 lydict_insert(ctx, buf, len, filepath);
327 }
328#else
329 /* get URI if there is /proc */
330 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
331 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
332 lydict_insert(ctx, path, len, filepath);
333 }
334#endif
335 break;
336 case LY_IN_MEMORY:
337 case LY_IN_FILE:
338 /* nothing to do */
339 break;
340 default:
341 LOGINT(ctx);
342 break;
343 }
344}
345
Michal Vaskod0625d72022-10-06 15:02:50 +0200346static 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 +0100347 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200348static 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 +0100349 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200350static 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 +0100351 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200352static 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 +0100353 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200354static 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 +0100355 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200356static 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 +0100357 struct lysp_node **siblings);
358
Radek Krejci335332a2019-09-05 13:03:35 +0200359static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200360lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200361{
Radek Krejci857189e2020-09-01 13:26:36 +0200362 uint8_t prefix = 0;
363 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200364 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200365 size_t utf8_char_len;
366
367 while (*val) {
368 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200369 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200370
371 switch (val_type) {
372 case Y_IDENTIF_ARG:
373 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
374 break;
375 case Y_PREF_IDENTIF_ARG:
376 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
377 break;
378 case Y_STR_ARG:
379 case Y_MAYBE_STR_ARG:
380 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
381 break;
382 }
383 first = 0;
384 }
385
386 return LY_SUCCESS;
387}
388
389/**
390 * @brief Parse extension instance.
391 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100392 * @param[in] ctx parser context.
393 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100394 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200395 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
396 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200397 * @return LY_ERR values.
398 */
399static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200400lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200401 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200402{
403 struct lysp_ext_instance *e;
404
Michal Vaskob36053d2020-03-26 15:49:30 +0100405 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200406
407 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200408 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100409 e->parent_stmt = insubstmt;
410 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200411 e->parsed = NULL;
Radek Krejci335332a2019-09-05 13:03:35 +0200412 /* TODO (duplicate) e->child = stmt->child; */
413
414 /* get optional argument */
415 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200416 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200417 }
418
419 return LY_SUCCESS;
420}
421
422/**
423 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
424 * description, etc...
425 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100426 * @param[in] ctx parser context.
427 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200428 * @param[in] substmt_index Index of this substatement.
429 * @param[in,out] value Place to store the parsed value.
430 * @param[in] arg Type of the YANG keyword argument (of the value).
431 * @param[in,out] exts Extension instances to add to.
432 *
433 * @return LY_ERR values.
434 */
435static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200436lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
437 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200438{
Radek Krejci335332a2019-09-05 13:03:35 +0200439 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200440 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200441 return LY_EVALID;
442 }
443
444 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200445 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200446
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100447 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
448 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200449 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100450 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200451 break;
452 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200453 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200454 return LY_EVALID;
455 }
456 }
457 return LY_SUCCESS;
458}
459
460/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200461 * @brief Parse a qname that can have more instances such as if-feature.
462 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100463 * @param[in] ctx parser context.
464 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200465 * @param[in,out] qnames Parsed qnames to add to.
466 * @param[in] arg Type of the expected argument.
467 * @param[in,out] exts Extension instances to add to.
468 *
469 * @return LY_ERR values.
470 */
471static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200472lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
473 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200474{
475 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200476
477 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
478
479 /* allocate new pointer */
480 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
481 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100482 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200483
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100484 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
485 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200486 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100487 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200488 break;
489 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200490 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200491 return LY_EVALID;
492 }
493 }
494 return LY_SUCCESS;
495}
496
497/**
Radek Krejci335332a2019-09-05 13:03:35 +0200498 * @brief Parse a generic text field that can have more instances such as base.
499 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100500 * @param[in] ctx parser context.
501 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200502 * @param[in,out] texts Parsed values to add to.
503 * @param[in] arg Type of the expected argument.
504 * @param[in,out] exts Extension instances to add to.
505 *
506 * @return LY_ERR values.
507 */
508static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200509lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
510 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200511{
512 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200513
514 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
515
516 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100517 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200518 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200519
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100520 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
521 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200522 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100523 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200524 break;
525 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200526 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200527 return LY_EVALID;
528 }
529 }
530 return LY_SUCCESS;
531}
532
533/**
534 * @brief Parse the status statement.
535 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100536 * @param[in] ctx parser context.
537 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200538 * @param[in,out] flags Flags to add to.
539 * @param[in,out] exts Extension instances to add to.
540 *
541 * @return LY_ERR values.
542 */
543static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200544lysp_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 +0200545{
546 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200547
548 if (*flags & LYS_STATUS_MASK) {
549 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
550 return LY_EVALID;
551 }
552
553 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
554 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100555 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200556 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100557 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200558 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100559 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200560 *flags |= LYS_STATUS_OBSLT;
561 } else {
562 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
563 return LY_EVALID;
564 }
565
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100566 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
567 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200568 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100569 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200570 break;
571 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200572 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200573 return LY_EVALID;
574 }
575 }
576 return LY_SUCCESS;
577}
578
579/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100580 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200581 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100582 * @param[in] ctx parser context.
583 * @param[in] stmt Source statement data from the parsed extension instance.
584 * @param[in,out] when_p When pointer to parse to.
585 *
586 * @return LY_ERR values.
587 */
588static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200589lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100590{
591 LY_ERR ret = LY_SUCCESS;
592 struct lysp_when *when;
593
594 if (*when_p) {
595 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
596 return LY_EVALID;
597 }
598
599 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
600
601 when = calloc(1, sizeof *when);
602 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
603 *when_p = when;
604
605 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
606
607 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
608 switch (child->kw) {
609 case LY_STMT_DESCRIPTION:
610 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
611 break;
612 case LY_STMT_REFERENCE:
613 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
614 break;
615 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100616 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100617 break;
618 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200619 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100620 return LY_EVALID;
621 }
622 }
623 return ret;
624}
625
626/**
627 * @brief Parse the config statement.
628 *
629 * @param[in] ctx parser context.
630 * @param[in] stmt Source statement data from the parsed extension instance.
631 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200632 * @param[in,out] exts Extension instances to add to.
633 *
634 * @return LY_ERR values.
635 */
636static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200637lysp_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 +0200638{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100639 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200640
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100641 if (*flags & LYS_CONFIG_MASK) {
642 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
643 return LY_EVALID;
644 }
645
646 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
647 arg_len = strlen(stmt->arg);
648 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
649 *flags |= LYS_CONFIG_W;
650 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
651 *flags |= LYS_CONFIG_R;
652 } else {
653 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
654 return LY_EVALID;
655 }
656
657 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
658 switch (child->kw) {
659 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100660 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100661 break;
662 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200663 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100664 return LY_EVALID;
665 }
666 }
667
668 return LY_SUCCESS;
669}
670
671/**
672 * @brief Parse the mandatory statement.
673 *
674 * @param[in] ctx parser context.
675 * @param[in] stmt Source statement data from the parsed extension instance.
676 * @param[in,out] flags Flags to add to.
677 * @param[in,out] exts Extension instances to add to.
678 *
679 * @return LY_ERR values.
680 */
681static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200682lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200683 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100684{
685 size_t arg_len;
686
687 if (*flags & LYS_MAND_MASK) {
688 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
689 return LY_EVALID;
690 }
691
692 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
693 arg_len = strlen(stmt->arg);
694 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
695 *flags |= LYS_MAND_TRUE;
696 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
697 *flags |= LYS_MAND_FALSE;
698 } else {
699 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
700 return LY_EVALID;
701 }
702
703 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
704 switch (child->kw) {
705 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100706 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100707 break;
708 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200709 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100710 return LY_EVALID;
711 }
712 }
713
714 return LY_SUCCESS;
715}
716
717/**
718 * @brief Parse a restriction such as range or length.
719 *
720 * @param[in] ctx parser context.
721 * @param[in] stmt Source statement data from the parsed extension instance.
722 * @param[in,out] exts Extension instances to add to.
723 *
724 * @return LY_ERR values.
725 */
726static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200727lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100728{
Radek Krejci335332a2019-09-05 13:03:35 +0200729 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200730 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100731 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200732
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100733 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
734 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200735 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100736 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200737 break;
738 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100739 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200740 break;
741 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100742 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200743 break;
744 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100745 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200746 break;
747 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100748 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200749 break;
750 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200751 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200752 return LY_EVALID;
753 }
754 }
755 return LY_SUCCESS;
756}
757
758/**
759 * @brief Parse a restriction that can have more instances such as must.
760 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100761 * @param[in] ctx parser context.
762 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200763 * @param[in,out] restrs Restrictions to add to.
764 *
765 * @return LY_ERR values.
766 */
767static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200768lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200769{
770 struct lysp_restr *restr;
771
Michal Vaskob36053d2020-03-26 15:49:30 +0100772 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100773 return lysp_stmt_restr(ctx, stmt, restr);
774}
775
776/**
777 * @brief Parse the anydata or anyxml statement.
778 *
779 * @param[in] ctx parser context.
780 * @param[in] stmt Source statement data from the parsed extension instance.
781 * @param[in,out] siblings Siblings to add to.
782 *
783 * @return LY_ERR values.
784 */
785static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200786lysp_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 +0100787{
788 struct lysp_node_anydata *any;
789
790 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
791
792 /* create new structure and insert into siblings */
793 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
794
795 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
796 any->parent = parent;
797
798 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
799
800 /* parse substatements */
801 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
802 switch (child->kw) {
803 case LY_STMT_CONFIG:
804 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
805 break;
806 case LY_STMT_DESCRIPTION:
807 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
808 break;
809 case LY_STMT_IF_FEATURE:
810 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
811 break;
812 case LY_STMT_MANDATORY:
813 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
814 break;
815 case LY_STMT_MUST:
816 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
817 break;
818 case LY_STMT_REFERENCE:
819 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
820 break;
821 case LY_STMT_STATUS:
822 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
823 break;
824 case LY_STMT_WHEN:
825 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
826 break;
827 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100828 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100829 break;
830 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200831 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
832 (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 +0100833 return LY_EVALID;
834 }
835 }
836
837 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200838}
839
840/**
841 * @brief Parse the value or position statement. Substatement of type enum statement.
842 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100843 * @param[in] ctx parser context.
844 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200845 * @param[in,out] value Value to write to.
846 * @param[in,out] flags Flags to write to.
847 * @param[in,out] exts Extension instances to add to.
848 *
849 * @return LY_ERR values.
850 */
851static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200852lysp_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 +0200853 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200854{
855 size_t arg_len;
856 char *ptr = NULL;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200857 long long int num = 0;
858 unsigned long long int unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200859
860 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200861 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200862 return LY_EVALID;
863 }
864 *flags |= LYS_SET_VALUE;
865
866 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
867
868 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100869 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
870 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200871 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200872 goto error;
873 }
874
875 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100876 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200877 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200878 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200879 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200880 goto error;
881 }
882 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200883 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200884 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200885 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200886 goto error;
887 }
888 }
889 /* we have not parsed the whole argument */
890 if ((size_t)(ptr - stmt->arg) != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200891 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200892 goto error;
893 }
894 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200895 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200896 goto error;
897 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100898 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200899 *value = num;
900 } else {
901 *value = unum;
902 }
903
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100904 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
905 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200906 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100907 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 +0200908 break;
909 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200910 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200911 return LY_EVALID;
912 }
913 }
914 return LY_SUCCESS;
915
916error:
917 return LY_EVALID;
918}
919
920/**
921 * @brief Parse the enum or bit statement. Substatement of type statement.
922 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100923 * @param[in] ctx parser context.
924 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200925 * @param[in,out] enums Enums or bits to add to.
926 *
927 * @return LY_ERR values.
928 */
929static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200930lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +0200931{
932 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200933
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100934 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 +0200935
Michal Vaskob36053d2020-03-26 15:49:30 +0100936 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200937
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100938 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +0200939 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
940 } /* else nothing specific for YANG_BIT */
941
Radek Krejci011e4aa2020-09-04 15:22:31 +0200942 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +0200943 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +0200944
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100945 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
946 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200947 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100948 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200949 break;
950 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +0200951 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100952 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200953 break;
954 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100955 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200956 break;
957 case LY_STMT_STATUS:
958 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
959 break;
960 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +0200961 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
962 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100963 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200964 break;
965 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +0200966 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
967 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100968 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200969 break;
970 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100971 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200972 break;
973 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200974 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200975 return LY_EVALID;
976 }
977 }
Michal Vasko193dacd2022-10-13 08:43:05 +0200978
Radek Krejci335332a2019-09-05 13:03:35 +0200979 return LY_SUCCESS;
980}
981
982/**
983 * @brief Parse the fraction-digits statement. Substatement of type statement.
984 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100985 * @param[in] ctx parser context.
986 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200987 * @param[in,out] fracdig Value to write to.
988 * @param[in,out] exts Extension instances to add to.
989 *
990 * @return LY_ERR values.
991 */
992static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200993lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +0200994 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200995{
996 char *ptr;
997 size_t arg_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200998 unsigned long long int num;
Radek Krejci335332a2019-09-05 13:03:35 +0200999
1000 if (*fracdig) {
1001 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1002 return LY_EVALID;
1003 }
1004
1005 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1006 arg_len = strlen(stmt->arg);
1007 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1008 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1009 return LY_EVALID;
1010 }
1011
1012 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001013 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001014 /* we have not parsed the whole argument */
1015 if ((size_t)(ptr - stmt->arg) != arg_len) {
1016 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1017 return LY_EVALID;
1018 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001019 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001020 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1021 return LY_EVALID;
1022 }
1023 *fracdig = num;
1024
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001025 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1026 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001027 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001028 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001029 break;
1030 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001031 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001032 return LY_EVALID;
1033 }
1034 }
1035 return LY_SUCCESS;
1036}
1037
1038/**
1039 * @brief Parse the require-instance statement. Substatement of type statement.
1040 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001041 * @param[in] ctx parser context.
1042 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001043 * @param[in,out] reqinst Value to write to.
1044 * @param[in,out] flags Flags to write to.
1045 * @param[in,out] exts Extension instances to add to.
1046 *
1047 * @return LY_ERR values.
1048 */
1049static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001050lysp_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 +02001051 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001052{
1053 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001054
1055 if (*flags & LYS_SET_REQINST) {
1056 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1057 return LY_EVALID;
1058 }
1059 *flags |= LYS_SET_REQINST;
1060
1061 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1062 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001063 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001064 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001065 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001066 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1067 return LY_EVALID;
1068 }
1069
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001070 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1071 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001072 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001073 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001074 break;
1075 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001076 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001077 return LY_EVALID;
1078 }
1079 }
1080 return LY_SUCCESS;
1081}
1082
1083/**
1084 * @brief Parse the modifier statement. Substatement of type pattern statement.
1085 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001086 * @param[in] ctx parser context.
1087 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001088 * @param[in,out] pat Value to write to.
1089 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001090 * @return LY_ERR values.
1091 */
1092static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001093lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001094 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001095{
1096 size_t arg_len;
1097 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001098
Radek Krejcif13b87b2020-12-01 22:02:17 +01001099 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001100 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1101 return LY_EVALID;
1102 }
1103
1104 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1105 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001106 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001107 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1108 return LY_EVALID;
1109 }
1110
1111 /* replace the value in the dictionary */
1112 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001113 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001114 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001115 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001116
Radek Krejcif13b87b2020-12-01 22:02:17 +01001117 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1118 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001119 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001120
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001121 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1122 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001123 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001124 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001125 break;
1126 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001127 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001128 return LY_EVALID;
1129 }
1130 }
1131 return LY_SUCCESS;
1132}
1133
1134/**
1135 * @brief Parse the pattern statement. Substatement of type statement.
1136 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001137 * @param[in] ctx parser context.
1138 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001139 * @param[in,out] patterns Restrictions to add to.
1140 *
1141 * @return LY_ERR values.
1142 */
1143static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001144lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001145{
1146 char *buf;
1147 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001148 struct lysp_restr *restr;
1149
1150 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001151 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001152 arg_len = strlen(stmt->arg);
1153
1154 /* add special meaning first byte */
1155 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001156 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001157 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001158 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001159 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001160 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001161 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001162
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001163 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1164 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001165 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001166 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001167 break;
1168 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001169 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001170 break;
1171 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001172 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001173 break;
1174 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001175 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001176 break;
1177 case LY_STMT_MODIFIER:
1178 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001179 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001180 break;
1181 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001182 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001183 break;
1184 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001185 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001186 return LY_EVALID;
1187 }
1188 }
1189 return LY_SUCCESS;
1190}
1191
1192/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001193 * @brief Parse the deviate statement. Substatement of deviation statement.
1194 *
1195 * @param[in] ctx parser context.
1196 * @param[in] stmt Source statement data from the parsed extension instance.
1197 * @param[in,out] devs Array of deviates to add to.
1198 * @param[in,out] exts Extension instances to add to.
1199 * @return LY_ERR values.
1200 */
1201static LY_ERR
1202lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1203{
1204 (void)stmt;
1205 (void)devs;
1206 (void)exts;
1207
1208 /* TODO */
1209 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1210 return LY_EINVAL;
1211}
1212
1213/**
1214 * @brief Parse the deviation statement.
1215 *
1216 * @param[in] ctx parser context.
1217 * @param[in] stmt Source statement data from the parsed extension instance.
1218 * @param[in,out] deviations Array of deviations to add to.
1219 * @return LY_ERR values.
1220 */
1221static LY_ERR
1222lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1223{
1224 struct lysp_deviation *dev;
1225
1226 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1227
1228 /* store nodeid */
1229 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1230 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1231
1232 /* parse substatements */
1233 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1234 switch (child->kw) {
1235 case LY_STMT_DESCRIPTION:
1236 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1237 break;
1238 case LY_STMT_DEVIATE:
1239 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1240 break;
1241 case LY_STMT_REFERENCE:
1242 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1243 break;
1244 case LY_STMT_EXTENSION_INSTANCE:
1245 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1246 break;
1247 default:
1248 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1249 return LY_EVALID;
1250 }
1251 }
1252
1253 return LY_SUCCESS;
1254}
1255
1256/**
1257 * @brief Parse the yang-version statement.
1258 *
1259 * @param[in] ctx parser context.
1260 * @param[in] stmt Source statement data from the parsed extension instance.
1261 * @param[out] version Version to write to.
1262 * @param[in,out] exts Extension instances to add to.
1263 * @return LY_ERR values.
1264 */
1265static LY_ERR
1266lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1267{
1268 if (*version) {
1269 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1270 return LY_EVALID;
1271 }
1272
1273 /* store flag */
1274 if (!strcmp(stmt->arg, "1")) {
1275 *version = LYS_VERSION_1_0;
1276 } else if (!strcmp(stmt->arg, "1.1")) {
1277 *version = LYS_VERSION_1_1;
1278 } else {
1279 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yang-version");
1280 return LY_EVALID;
1281 }
1282
1283 /* parse substatements */
1284 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1285 switch (child->kw) {
1286 case LY_STMT_EXTENSION_INSTANCE:
1287 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1288 break;
1289 default:
1290 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1291 return LY_EVALID;
1292 }
1293 }
1294
1295 return LY_SUCCESS;
1296}
1297
1298/**
1299 * @brief Parse the module statement.
1300 *
1301 * @param[in] ctx parser context.
1302 * @param[in] stmt Source statement data from the parsed extension instance.
1303 * @param[in,out] mod Module to fill.
1304 * @return LY_ERR values.
1305 */
1306static LY_ERR
1307lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1308{
1309 (void)stmt;
1310 (void)mod;
1311
1312 /* TODO */
1313 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1314 return LY_EINVAL;
1315}
1316
1317/**
1318 * @brief Parse the submodule statement.
1319 *
1320 * @param[in] ctx parser context.
1321 * @param[in] stmt Source statement data from the parsed extension instance.
1322 * @param[in,out] submod Module to fill.
1323 * @return LY_ERR values.
1324 */
1325static LY_ERR
1326lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1327{
1328 (void)stmt;
1329 (void)submod;
1330
1331 /* TODO */
1332 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1333 return LY_EINVAL;
1334}
1335
1336/**
1337 * @brief Parse the yin-element statement. Substatement of argument statement.
1338 *
1339 * @param[in] ctx parser context.
1340 * @param[in] stmt Source statement data from the parsed extension instance.
1341 * @param[in,out] flags Flags to write to.
1342 * @param[in,out] exts Extension instances to add to.
1343 * @return LY_ERR values.
1344 */
1345static LY_ERR
1346lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1347{
1348 if (*flags & LYS_YINELEM_MASK) {
1349 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1350 return LY_EVALID;
1351 }
1352
1353 /* store flag */
1354 if (!strcmp(stmt->arg, "true")) {
1355 *flags |= LYS_YINELEM_TRUE;
1356 } else if (!strcmp(stmt->arg, "false")) {
1357 *flags |= LYS_YINELEM_FALSE;
1358 } else {
1359 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yin-element");
1360 return LY_EVALID;
1361 }
1362
1363 /* parse substatements */
1364 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1365 switch (child->kw) {
1366 case LY_STMT_EXTENSION_INSTANCE:
1367 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1368 break;
1369 default:
1370 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1371 return LY_EVALID;
1372 }
1373 }
1374
1375 return LY_SUCCESS;
1376}
1377
1378/**
1379 * @brief Parse the argument statement. Substatement of extension statement.
1380 *
1381 * @param[in] ctx parser context.
1382 * @param[in] stmt Source statement data from the parsed extension instance.
1383 * @param[in,out] ex Extension to fill.
1384 * @return LY_ERR values.
1385 */
1386static LY_ERR
1387lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1388{
1389 if (ex->argname) {
1390 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1391 return LY_EVALID;
1392 }
1393
1394 /* store argument name */
1395 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1396 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1397
1398 /* parse substatements */
1399 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1400 switch (child->kw) {
1401 case LY_STMT_YIN_ELEMENT:
1402 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1403 break;
1404 case LY_STMT_EXTENSION_INSTANCE:
1405 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1406 break;
1407 default:
1408 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1409 return LY_EVALID;
1410 }
1411 }
1412
1413 return LY_SUCCESS;
1414}
1415
1416/**
1417 * @brief Parse the extension statement.
1418 *
1419 * @param[in] ctx parser context.
1420 * @param[in] stmt Source statement data from the parsed extension instance.
1421 * @param[in,out] extensions Array of extensions to add to.
1422 * @return LY_ERR values.
1423 */
1424static LY_ERR
1425lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1426{
1427 struct lysp_ext *ex;
1428
1429 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1430
1431 /* store name */
1432 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1433 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1434
1435 /* parse substatements */
1436 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1437 switch (child->kw) {
1438 case LY_STMT_DESCRIPTION:
1439 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1440 break;
1441 case LY_STMT_REFERENCE:
1442 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1443 break;
1444 case LY_STMT_STATUS:
1445 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1446 break;
1447 case LY_STMT_ARGUMENT:
1448 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1449 break;
1450 case LY_STMT_EXTENSION_INSTANCE:
1451 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1452 break;
1453 default:
1454 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1455 return LY_EVALID;
1456 }
1457 }
1458
1459 return LY_SUCCESS;
1460}
1461
1462/**
1463 * @brief Parse the feature statement.
1464 *
1465 * @param[in] ctx parser context.
1466 * @param[in] stmt Source statement data from the parsed extension instance.
1467 * @param[in,out] features Array of features to add to.
1468 * @return LY_ERR values.
1469 */
1470static LY_ERR
1471lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1472{
1473 struct lysp_feature *feat;
1474
1475 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1476
1477 /* store name */
1478 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1479 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1480
1481 /* parse substatements */
1482 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1483 switch (child->kw) {
1484 case LY_STMT_DESCRIPTION:
1485 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1486 break;
1487 case LY_STMT_IF_FEATURE:
1488 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1489 break;
1490 case LY_STMT_REFERENCE:
1491 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1492 break;
1493 case LY_STMT_STATUS:
1494 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1495 break;
1496 case LY_STMT_EXTENSION_INSTANCE:
1497 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1498 break;
1499 default:
1500 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1501 return LY_EVALID;
1502 }
1503 }
1504
1505 return LY_SUCCESS;
1506}
1507
1508/**
1509 * @brief Parse the identity statement.
1510 *
1511 * @param[in] ctx parser context.
1512 * @param[in] stmt Source statement data from the parsed extension instance.
1513 * @param[in,out] identities Array of identities to add to.
1514 * @return LY_ERR values.
1515 */
1516static LY_ERR
1517lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1518{
1519 struct lysp_ident *ident;
1520
1521 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1522
1523 /* store name */
1524 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1525 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1526
1527 /* parse substatements */
1528 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1529 switch (child->kw) {
1530 case LY_STMT_DESCRIPTION:
1531 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1532 break;
1533 case LY_STMT_IF_FEATURE:
1534 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1535 break;
1536 case LY_STMT_REFERENCE:
1537 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1538 break;
1539 case LY_STMT_STATUS:
1540 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1541 break;
1542 case LY_STMT_BASE:
1543 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1544 break;
1545 case LY_STMT_EXTENSION_INSTANCE:
1546 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1547 break;
1548 default:
1549 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1550 return LY_EVALID;
1551 }
1552 }
1553
1554 return LY_SUCCESS;
1555}
1556
1557/**
1558 * @brief Parse the import statement.
1559 *
1560 * @param[in] ctx parser context.
1561 * @param[in] stmt Source statement data from the parsed extension instance.
1562 * @param[in,out] imports Array of imports to add to.
1563 * @return LY_ERR values.
1564 */
1565static LY_ERR
1566lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1567{
1568 struct lysp_import *imp;
1569 const char *str = NULL;
1570
1571 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1572
1573 /* store name */
1574 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1575 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1576
1577 /* parse substatements */
1578 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1579 switch (child->kw) {
1580 case LY_STMT_PREFIX:
1581 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1582 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1583 break;
1584 case LY_STMT_DESCRIPTION:
1585 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1586 break;
1587 case LY_STMT_REFERENCE:
1588 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1589 break;
1590 case LY_STMT_REVISION_DATE:
1591 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1592 strcpy(imp->rev, str);
1593 lydict_remove(PARSER_CTX(ctx), str);
1594 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1595 break;
1596 case LY_STMT_EXTENSION_INSTANCE:
1597 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1598 break;
1599 default:
1600 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1601 return LY_EVALID;
1602 }
1603 }
1604
1605 return LY_SUCCESS;
1606}
1607
1608/**
1609 * @brief Parse the include statement.
1610 *
1611 * @param[in] ctx parser context.
1612 * @param[in] stmt Source statement data from the parsed extension instance.
1613 * @param[in,out] includes Array of identities to add to.
1614 * @return LY_ERR values.
1615 */
1616static LY_ERR
1617lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1618{
1619 struct lysp_include *inc;
1620 const char *str = NULL;
1621
1622 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1623
1624 /* store name */
1625 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1626 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1627
1628 /* parse substatements */
1629 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1630 switch (child->kw) {
1631 case LY_STMT_DESCRIPTION:
1632 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1633 break;
1634 case LY_STMT_REFERENCE:
1635 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1636 break;
1637 case LY_STMT_REVISION_DATE:
1638 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1639 strcpy(inc->rev, str);
1640 lydict_remove(PARSER_CTX(ctx), str);
1641 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1642 break;
1643 case LY_STMT_EXTENSION_INSTANCE:
1644 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1645 break;
1646 default:
1647 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1648 return LY_EVALID;
1649 }
1650 }
1651
1652 return LY_SUCCESS;
1653}
1654
1655/**
1656 * @brief Parse the revision statement.
1657 *
1658 * @param[in] ctx parser context.
1659 * @param[in] stmt Source statement data from the parsed extension instance.
1660 * @param[in,out] includes Array of identities to add to.
1661 * @return LY_ERR values.
1662 */
1663static LY_ERR
1664lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1665{
1666 struct lysp_revision *rev;
1667
1668 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1669
1670 /* store date */
1671 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, LY_REV_SIZE - 1, "revision"));
1672 strcpy(rev->date, stmt->arg);
1673
1674 /* parse substatements */
1675 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1676 switch (child->kw) {
1677 case LY_STMT_DESCRIPTION:
1678 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1679 break;
1680 case LY_STMT_REFERENCE:
1681 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1682 break;
1683 case LY_STMT_EXTENSION_INSTANCE:
1684 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1685 break;
1686 default:
1687 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1688 return LY_EVALID;
1689 }
1690 }
1691
1692 return LY_SUCCESS;
1693}
1694
1695/**
Radek Krejci335332a2019-09-05 13:03:35 +02001696 * @brief Parse the type statement.
1697 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001698 * @param[in] ctx parser context.
1699 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001700 * @param[in,out] type Type to wrote to.
1701 *
1702 * @return LY_ERR values.
1703 */
1704static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001705lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001706{
1707 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001708 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001709 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001710
1711 if (type->name) {
1712 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1713 return LY_EVALID;
1714 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001715
1716 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001717 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001718 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001719
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001720 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1721 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001722 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001723 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001724 type->flags |= LYS_SET_BASE;
1725 break;
1726 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001727 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001728 type->flags |= LYS_SET_BIT;
1729 break;
1730 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001731 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001732 type->flags |= LYS_SET_ENUM;
1733 break;
1734 case LY_STMT_FRACTION_DIGITS:
1735 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1736 type->flags |= LYS_SET_FRDIGITS;
1737 break;
1738 case LY_STMT_LENGTH:
1739 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001740 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001741 return LY_EVALID;
1742 }
1743 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001744 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001745
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001746 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001747 type->flags |= LYS_SET_LENGTH;
1748 break;
1749 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001750 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001751 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001752 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001753 lydict_remove(PARSER_CTX(ctx), str_path);
1754 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001755 type->flags |= LYS_SET_PATH;
1756 break;
1757 case LY_STMT_PATTERN:
1758 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1759 type->flags |= LYS_SET_PATTERN;
1760 break;
1761 case LY_STMT_RANGE:
1762 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001763 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001764 return LY_EVALID;
1765 }
1766 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001767 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001768
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001769 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001770 type->flags |= LYS_SET_RANGE;
1771 break;
1772 case LY_STMT_REQUIRE_INSTANCE:
1773 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001774 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001775 break;
1776 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001777 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001778 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1779 type->flags |= LYS_SET_TYPE;
1780 break;
1781 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001782 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001783 break;
1784 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001785 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001786 return LY_EVALID;
1787 }
1788 }
1789 return LY_SUCCESS;
1790}
1791
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001792/**
1793 * @brief Parse the leaf statement.
1794 *
1795 * @param[in] ctx parser context.
1796 * @param[in] stmt Source statement data from the parsed extension instance.
1797 * @param[in] parent Parent node to connect to (not into).
1798 * @param[in,out] siblings Siblings to add to.
1799 *
1800 * @return LY_ERR values.
1801 */
1802static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001803lysp_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 +01001804{
1805 struct lysp_node_leaf *leaf;
1806
1807 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1808
1809 /* create new leaf structure */
1810 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1811 leaf->nodetype = LYS_LEAF;
1812 leaf->parent = parent;
1813
1814 /* get name */
1815 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1816
1817 /* parse substatements */
1818 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1819 switch (child->kw) {
1820 case LY_STMT_CONFIG:
1821 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1822 break;
1823 case LY_STMT_DEFAULT:
1824 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 +01001825 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001826 break;
1827 case LY_STMT_DESCRIPTION:
1828 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1829 break;
1830 case LY_STMT_IF_FEATURE:
1831 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1832 break;
1833 case LY_STMT_MANDATORY:
1834 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1835 break;
1836 case LY_STMT_MUST:
1837 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1838 break;
1839 case LY_STMT_REFERENCE:
1840 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1841 break;
1842 case LY_STMT_STATUS:
1843 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1844 break;
1845 case LY_STMT_TYPE:
1846 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1847 break;
1848 case LY_STMT_UNITS:
1849 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1850 break;
1851 case LY_STMT_WHEN:
1852 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1853 break;
1854 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001855 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001856 break;
1857 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001858 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001859 return LY_EVALID;
1860 }
1861 }
1862
1863 /* mandatory substatements */
1864 if (!leaf->type.name) {
1865 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1866 return LY_EVALID;
1867 }
1868
1869 return LY_SUCCESS;
1870}
1871
1872/**
1873 * @brief Parse the max-elements statement.
1874 *
1875 * @param[in] ctx parser context.
1876 * @param[in] stmt Source statement data from the parsed extension instance.
1877 * @param[in,out] max Value to write to.
1878 * @param[in,out] flags Flags to write to.
1879 * @param[in,out] exts Extension instances to add to.
1880 *
1881 * @return LY_ERR values.
1882 */
1883static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001884lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
1885 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001886{
1887 size_t arg_len;
1888 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001889 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001890
1891 if (*flags & LYS_SET_MAX) {
1892 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1893 return LY_EVALID;
1894 }
1895 *flags |= LYS_SET_MAX;
1896
1897 /* get value */
1898 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1899 arg_len = strlen(stmt->arg);
1900
1901 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1902 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1903 return LY_EVALID;
1904 }
1905
1906 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1907 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001908 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001909 /* we have not parsed the whole argument */
1910 if ((size_t)(ptr - stmt->arg) != arg_len) {
1911 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1912 return LY_EVALID;
1913 }
1914 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1915 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1916 return LY_EVALID;
1917 }
1918
1919 *max = num;
1920 } else {
1921 /* unbounded */
1922 *max = 0;
1923 }
1924
1925 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1926 switch (child->kw) {
1927 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001928 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001929 break;
1930 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001931 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001932 return LY_EVALID;
1933 }
1934 }
1935
1936 return LY_SUCCESS;
1937}
1938
1939/**
1940 * @brief Parse the min-elements statement.
1941 *
1942 * @param[in] ctx parser context.
1943 * @param[in] stmt Source statement data from the parsed extension instance.
1944 * @param[in,out] min Value to write to.
1945 * @param[in,out] flags Flags to write to.
1946 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001947 * @return LY_ERR values.
1948 */
1949static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001950lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
1951 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001952{
1953 size_t arg_len;
1954 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001955 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001956
1957 if (*flags & LYS_SET_MIN) {
1958 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
1959 return LY_EVALID;
1960 }
1961 *flags |= LYS_SET_MIN;
1962
1963 /* get value */
1964 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1965 arg_len = strlen(stmt->arg);
1966
1967 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
1968 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1969 return LY_EVALID;
1970 }
1971
1972 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001973 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001974 /* we have not parsed the whole argument */
1975 if ((size_t)(ptr - stmt->arg) != arg_len) {
1976 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1977 return LY_EVALID;
1978 }
1979 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1980 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
1981 return LY_EVALID;
1982 }
1983 *min = num;
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_MIN_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), "min-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 ordered-by statement.
2001 *
2002 * @param[in] ctx parser context.
2003 * @param[in] stmt Source statement data from the parsed extension instance.
2004 * @param[in,out] flags Flags to write to.
2005 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002006 * @return LY_ERR values.
2007 */
2008static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002009lysp_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 +01002010{
2011 size_t arg_len;
2012
2013 if (*flags & LYS_ORDBY_MASK) {
2014 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2015 return LY_EVALID;
2016 }
2017
2018 /* get value */
2019 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2020 arg_len = strlen(stmt->arg);
2021 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2022 *flags |= LYS_MAND_TRUE;
2023 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2024 *flags |= LYS_MAND_FALSE;
2025 } else {
2026 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2027 return LY_EVALID;
2028 }
2029
2030 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2031 switch (child->kw) {
2032 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002033 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002034 break;
2035 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002036 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002037 return LY_EVALID;
2038 }
2039 }
2040
2041 return LY_SUCCESS;
2042}
2043
2044/**
2045 * @brief Parse the leaf-list statement.
2046 *
2047 * @param[in] ctx parser context.
2048 * @param[in] stmt Source statement data from the parsed extension instance.
2049 * @param[in] parent Parent node to connect to (not into).
2050 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002051 * @return LY_ERR values.
2052 */
2053static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002054lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002055 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002056{
2057 struct lysp_node_leaflist *llist;
2058
2059 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2060
2061 /* create new leaf-list structure */
2062 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2063 llist->nodetype = LYS_LEAFLIST;
2064 llist->parent = parent;
2065
2066 /* get name */
2067 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2068
2069 /* parse substatements */
2070 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2071 switch (child->kw) {
2072 case LY_STMT_CONFIG:
2073 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2074 break;
2075 case LY_STMT_DEFAULT:
2076 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2077 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2078 break;
2079 case LY_STMT_DESCRIPTION:
2080 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2081 break;
2082 case LY_STMT_IF_FEATURE:
2083 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2084 break;
2085 case LY_STMT_MAX_ELEMENTS:
2086 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2087 break;
2088 case LY_STMT_MIN_ELEMENTS:
2089 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2090 break;
2091 case LY_STMT_MUST:
2092 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2093 break;
2094 case LY_STMT_ORDERED_BY:
2095 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2096 break;
2097 case LY_STMT_REFERENCE:
2098 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2099 break;
2100 case LY_STMT_STATUS:
2101 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2102 break;
2103 case LY_STMT_TYPE:
2104 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2105 break;
2106 case LY_STMT_UNITS:
2107 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2108 break;
2109 case LY_STMT_WHEN:
2110 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2111 break;
2112 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002113 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002114 break;
2115 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002116 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002117 return LY_EVALID;
2118 }
2119 }
2120
2121 /* mandatory substatements */
2122 if (!llist->type.name) {
2123 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2124 return LY_EVALID;
2125 }
2126
2127 return LY_SUCCESS;
2128}
2129
2130/**
2131 * @brief Parse the refine statement.
2132 *
2133 * @param[in] ctx parser context.
2134 * @param[in] stmt Source statement data from the parsed extension instance.
2135 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002136 * @return LY_ERR values.
2137 */
2138static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002139lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002140{
2141 struct lysp_refine *rf;
2142
2143 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2144
2145 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2146
2147 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2148
2149 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2150 switch (child->kw) {
2151 case LY_STMT_CONFIG:
2152 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2153 break;
2154 case LY_STMT_DEFAULT:
2155 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2156 break;
2157 case LY_STMT_DESCRIPTION:
2158 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2159 break;
2160 case LY_STMT_IF_FEATURE:
2161 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2162 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2163 break;
2164 case LY_STMT_MAX_ELEMENTS:
2165 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2166 break;
2167 case LY_STMT_MIN_ELEMENTS:
2168 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2169 break;
2170 case LY_STMT_MUST:
2171 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2172 break;
2173 case LY_STMT_MANDATORY:
2174 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2175 break;
2176 case LY_STMT_REFERENCE:
2177 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2178 break;
2179 case LY_STMT_PRESENCE:
2180 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2181 break;
2182 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002183 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002184 break;
2185 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002186 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002187 return LY_EVALID;
2188 }
2189 }
2190
2191 return LY_SUCCESS;
2192}
2193
2194/**
2195 * @brief Parse the typedef statement.
2196 *
2197 * @param[in] ctx parser context.
2198 * @param[in] stmt Source statement data from the parsed extension instance.
2199 * @param[in] parent Parent node to connect to (not into).
2200 * @param[in,out] typedefs Typedefs to add to.
2201 *
2202 * @return LY_ERR values.
2203 */
2204static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002205lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002206 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002207{
2208 struct lysp_tpdf *tpdf;
2209
2210 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2211
2212 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2213
2214 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2215
2216 /* parse substatements */
2217 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2218 switch (child->kw) {
2219 case LY_STMT_DEFAULT:
2220 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 +01002221 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002222 break;
2223 case LY_STMT_DESCRIPTION:
2224 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2225 break;
2226 case LY_STMT_REFERENCE:
2227 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2228 break;
2229 case LY_STMT_STATUS:
2230 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2231 break;
2232 case LY_STMT_TYPE:
2233 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2234 break;
2235 case LY_STMT_UNITS:
2236 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2237 break;
2238 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002239 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002240 break;
2241 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002242 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002243 return LY_EVALID;
2244 }
2245 }
2246
2247 /* mandatory substatements */
2248 if (!tpdf->type.name) {
2249 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2250 return LY_EVALID;
2251 }
2252
2253 /* store data for collision check */
2254 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2255 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2256 }
2257
2258 return LY_SUCCESS;
2259}
2260
2261/**
2262 * @brief Parse the input or output statement.
2263 *
2264 * @param[in] ctx parser context.
2265 * @param[in] stmt Source statement data from the parsed extension instance.
2266 * @param[in] parent Parent node to connect to (not into).
2267 * @param[in,out] inout_p Input/output pointer to write to.
2268 *
2269 * @return LY_ERR values.
2270 */
2271static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002272lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002273 struct lysp_node_action_inout *inout_p)
2274{
2275 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002276 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002277 return LY_EVALID;
2278 }
2279
2280 /* initiate structure */
2281 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2282 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2283 inout_p->parent = parent;
2284
2285 /* parse substatements */
2286 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2287 switch (child->kw) {
2288 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002289 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002290 /* fall through */
2291 case LY_STMT_ANYXML:
2292 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2293 break;
2294 case LY_STMT_CHOICE:
2295 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2296 break;
2297 case LY_STMT_CONTAINER:
2298 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2299 break;
2300 case LY_STMT_LEAF:
2301 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2302 break;
2303 case LY_STMT_LEAF_LIST:
2304 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2305 break;
2306 case LY_STMT_LIST:
2307 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2308 break;
2309 case LY_STMT_USES:
2310 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2311 break;
2312 case LY_STMT_TYPEDEF:
2313 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2314 break;
2315 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002316 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002317 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2318 break;
2319 case LY_STMT_GROUPING:
2320 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2321 break;
2322 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002323 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002324 break;
2325 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002326 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002327 return LY_EVALID;
2328 }
2329 }
2330
2331 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002332 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002333 return LY_EVALID;
2334 }
2335
2336 return LY_SUCCESS;
2337}
2338
2339/**
2340 * @brief Parse the action statement.
2341 *
2342 * @param[in] ctx parser context.
2343 * @param[in] stmt Source statement data from the parsed extension instance.
2344 * @param[in] parent Parent node to connect to (not into).
2345 * @param[in,out] actions Actions to add to.
2346 *
2347 * @return LY_ERR values.
2348 */
2349static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002350lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002351 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002352{
2353 struct lysp_node_action *act;
2354
2355 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2356
2357 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2358
2359 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2360 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2361 act->parent = parent;
2362
2363 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2364 switch (child->kw) {
2365 case LY_STMT_DESCRIPTION:
2366 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2367 break;
2368 case LY_STMT_IF_FEATURE:
2369 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2370 break;
2371 case LY_STMT_REFERENCE:
2372 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2373 break;
2374 case LY_STMT_STATUS:
2375 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2376 break;
2377
2378 case LY_STMT_INPUT:
2379 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2380 break;
2381 case LY_STMT_OUTPUT:
2382 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2383 break;
2384
2385 case LY_STMT_TYPEDEF:
2386 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2387 break;
2388 case LY_STMT_GROUPING:
2389 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2390 break;
2391 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002392 LY_CHECK_RET(lysp_stmt_ext(ctx, child, parent ? LY_STMT_ACTION : LY_STMT_RPC, 0, &act->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002393 break;
2394 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002395 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002396 return LY_EVALID;
2397 }
2398 }
2399
2400 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2401 if (!act->input.nodetype) {
2402 act->input.nodetype = LYS_INPUT;
2403 act->input.parent = &act->node;
2404 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2405 }
2406 if (!act->output.nodetype) {
2407 act->output.nodetype = LYS_OUTPUT;
2408 act->output.parent = &act->node;
2409 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2410 }
2411
2412 return LY_SUCCESS;
2413}
2414
2415/**
2416 * @brief Parse the notification statement.
2417 *
2418 * @param[in] ctx parser context.
2419 * @param[in] stmt Source statement data from the parsed extension instance.
2420 * @param[in] parent Parent node to connect to (not into).
2421 * @param[in,out] notifs Notifications to add to.
2422 *
2423 * @return LY_ERR values.
2424 */
2425static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002426lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002427 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002428{
2429 struct lysp_node_notif *notif;
2430
2431 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2432
2433 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2434
2435 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2436 notif->nodetype = LYS_NOTIF;
2437 notif->parent = parent;
2438
2439 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2440 switch (child->kw) {
2441 case LY_STMT_DESCRIPTION:
2442 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2443 break;
2444 case LY_STMT_IF_FEATURE:
2445 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2446 break;
2447 case LY_STMT_REFERENCE:
2448 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2449 break;
2450 case LY_STMT_STATUS:
2451 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2452 break;
2453
2454 case LY_STMT_ANYDATA:
2455 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2456 /* fall through */
2457 case LY_STMT_ANYXML:
2458 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2459 break;
2460 case LY_STMT_CHOICE:
2461 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2462 break;
2463 case LY_STMT_CONTAINER:
2464 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2465 break;
2466 case LY_STMT_LEAF:
2467 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2468 break;
2469 case LY_STMT_LEAF_LIST:
2470 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2471 break;
2472 case LY_STMT_LIST:
2473 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2474 break;
2475 case LY_STMT_USES:
2476 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2477 break;
2478
2479 case LY_STMT_MUST:
2480 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2481 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2482 break;
2483 case LY_STMT_TYPEDEF:
2484 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2485 break;
2486 case LY_STMT_GROUPING:
2487 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2488 break;
2489 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002490 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002491 break;
2492 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002493 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002494 return LY_EVALID;
2495 }
2496 }
2497
2498 return LY_SUCCESS;
2499}
2500
2501/**
2502 * @brief Parse the grouping statement.
2503 *
2504 * @param[in] ctx parser context.
2505 * @param[in] stmt Source statement data from the parsed extension instance.
2506 * @param[in] parent Parent node to connect to (not into).
2507 * @param[in,out] groupings Groupings to add to.
2508 *
2509 * @return LY_ERR values.
2510 */
2511static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002512lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002513 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002514{
2515 struct lysp_node_grp *grp;
2516
2517 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2518
2519 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2520
2521 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2522 grp->nodetype = LYS_GROUPING;
2523 grp->parent = parent;
2524
2525 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2526 switch (child->kw) {
2527 case LY_STMT_DESCRIPTION:
2528 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2529 break;
2530 case LY_STMT_REFERENCE:
2531 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2532 break;
2533 case LY_STMT_STATUS:
2534 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2535 break;
2536
2537 case LY_STMT_ANYDATA:
2538 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2539 /* fall through */
2540 case LY_STMT_ANYXML:
2541 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2542 break;
2543 case LY_STMT_CHOICE:
2544 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2545 break;
2546 case LY_STMT_CONTAINER:
2547 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2548 break;
2549 case LY_STMT_LEAF:
2550 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2551 break;
2552 case LY_STMT_LEAF_LIST:
2553 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2554 break;
2555 case LY_STMT_LIST:
2556 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2557 break;
2558 case LY_STMT_USES:
2559 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2560 break;
2561
2562 case LY_STMT_TYPEDEF:
2563 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2564 break;
2565 case LY_STMT_ACTION:
2566 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2567 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2568 break;
2569 case LY_STMT_GROUPING:
2570 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2571 break;
2572 case LY_STMT_NOTIFICATION:
2573 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2574 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2575 break;
2576 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002577 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002578 break;
2579 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002580 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002581 return LY_EVALID;
2582 }
2583 }
2584
2585 return LY_SUCCESS;
2586}
2587
2588/**
2589 * @brief Parse the augment statement.
2590 *
2591 * @param[in] ctx parser context.
2592 * @param[in] stmt Source statement data from the parsed extension instance.
2593 * @param[in] parent Parent node to connect to (not into).
2594 * @param[in,out] augments Augments to add to.
2595 *
2596 * @return LY_ERR values.
2597 */
2598static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002599lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002600 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002601{
2602 struct lysp_node_augment *aug;
2603
2604 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2605
2606 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2607
2608 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2609 aug->nodetype = LYS_AUGMENT;
2610 aug->parent = parent;
2611
2612 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2613 switch (child->kw) {
2614 case LY_STMT_DESCRIPTION:
2615 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2616 break;
2617 case LY_STMT_IF_FEATURE:
2618 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2619 break;
2620 case LY_STMT_REFERENCE:
2621 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2622 break;
2623 case LY_STMT_STATUS:
2624 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2625 break;
2626 case LY_STMT_WHEN:
2627 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2628 break;
2629
2630 case LY_STMT_ANYDATA:
2631 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2632 /* fall through */
2633 case LY_STMT_ANYXML:
2634 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2635 break;
2636 case LY_STMT_CASE:
2637 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2638 break;
2639 case LY_STMT_CHOICE:
2640 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2641 break;
2642 case LY_STMT_CONTAINER:
2643 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2644 break;
2645 case LY_STMT_LEAF:
2646 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2647 break;
2648 case LY_STMT_LEAF_LIST:
2649 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2650 break;
2651 case LY_STMT_LIST:
2652 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2653 break;
2654 case LY_STMT_USES:
2655 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2656 break;
2657
2658 case LY_STMT_ACTION:
2659 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2660 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2661 break;
2662 case LY_STMT_NOTIFICATION:
2663 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2664 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2665 break;
2666 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002667 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002668 break;
2669 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002670 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002671 return LY_EVALID;
2672 }
2673 }
2674
2675 return LY_SUCCESS;
2676}
2677
2678/**
2679 * @brief Parse the uses statement.
2680 *
2681 * @param[in] ctx parser context.
2682 * @param[in] stmt Source statement data from the parsed extension instance.
2683 * @param[in] parent Parent node to connect to (not into).
2684 * @param[in,out] siblings Siblings to add to.
2685 *
2686 * @return LY_ERR values.
2687 */
2688static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002689lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002690 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002691{
2692 struct lysp_node_uses *uses;
2693
2694 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2695
2696 /* create uses structure */
2697 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2698
2699 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2700 uses->nodetype = LYS_USES;
2701 uses->parent = parent;
2702
2703 /* parse substatements */
2704 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2705 switch (child->kw) {
2706 case LY_STMT_DESCRIPTION:
2707 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2708 break;
2709 case LY_STMT_IF_FEATURE:
2710 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2711 break;
2712 case LY_STMT_REFERENCE:
2713 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2714 break;
2715 case LY_STMT_STATUS:
2716 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2717 break;
2718 case LY_STMT_WHEN:
2719 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2720 break;
2721
2722 case LY_STMT_REFINE:
2723 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2724 break;
2725 case LY_STMT_AUGMENT:
2726 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2727 break;
2728 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002729 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002730 break;
2731 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002732 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002733 return LY_EVALID;
2734 }
2735 }
2736
2737 return LY_SUCCESS;
2738}
2739
2740/**
2741 * @brief Parse the case statement.
2742 *
2743 * @param[in] ctx parser context.
2744 * @param[in] stmt Source statement data from the parsed extension instance.
2745 * @param[in] parent Parent node to connect to (not into).
2746 * @param[in,out] siblings Siblings to add to.
2747 *
2748 * @return LY_ERR values.
2749 */
2750static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002751lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002752 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002753{
2754 struct lysp_node_case *cas;
2755
2756 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2757
2758 /* create new case structure */
2759 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2760
2761 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2762 cas->nodetype = LYS_CASE;
2763 cas->parent = parent;
2764
2765 /* parse substatements */
2766 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2767 switch (child->kw) {
2768 case LY_STMT_DESCRIPTION:
2769 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2770 break;
2771 case LY_STMT_IF_FEATURE:
2772 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2773 break;
2774 case LY_STMT_REFERENCE:
2775 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2776 break;
2777 case LY_STMT_STATUS:
2778 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2779 break;
2780 case LY_STMT_WHEN:
2781 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2782 break;
2783
2784 case LY_STMT_ANYDATA:
2785 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2786 /* fall through */
2787 case LY_STMT_ANYXML:
2788 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2789 break;
2790 case LY_STMT_CHOICE:
2791 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2792 break;
2793 case LY_STMT_CONTAINER:
2794 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2795 break;
2796 case LY_STMT_LEAF:
2797 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2798 break;
2799 case LY_STMT_LEAF_LIST:
2800 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2801 break;
2802 case LY_STMT_LIST:
2803 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2804 break;
2805 case LY_STMT_USES:
2806 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2807 break;
2808 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002809 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002810 break;
2811 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002812 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002813 return LY_EVALID;
2814 }
2815 }
2816 return LY_SUCCESS;
2817}
2818
2819/**
2820 * @brief Parse the choice statement.
2821 *
2822 * @param[in] ctx parser context.
2823 * @param[in] stmt Source statement data from the parsed extension instance.
2824 * @param[in] parent Parent node to connect to (not into).
2825 * @param[in,out] siblings Siblings to add to.
2826 *
2827 * @return LY_ERR values.
2828 */
2829static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002830lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002831 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002832{
2833 struct lysp_node_choice *choice;
2834
2835 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2836
2837 /* create new choice structure */
2838 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2839
2840 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2841 choice->nodetype = LYS_CHOICE;
2842 choice->parent = parent;
2843
2844 /* parse substatements */
2845 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2846 switch (child->kw) {
2847 case LY_STMT_CONFIG:
2848 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2849 break;
2850 case LY_STMT_DESCRIPTION:
2851 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2852 break;
2853 case LY_STMT_IF_FEATURE:
2854 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2855 break;
2856 case LY_STMT_MANDATORY:
2857 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2858 break;
2859 case LY_STMT_REFERENCE:
2860 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2861 break;
2862 case LY_STMT_STATUS:
2863 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2864 break;
2865 case LY_STMT_WHEN:
2866 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2867 break;
2868 case LY_STMT_DEFAULT:
2869 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 +01002870 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002871 break;
2872 case LY_STMT_ANYDATA:
2873 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2874 /* fall through */
2875 case LY_STMT_ANYXML:
2876 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2877 break;
2878 case LY_STMT_CASE:
2879 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2880 break;
2881 case LY_STMT_CHOICE:
2882 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2883 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2884 break;
2885 case LY_STMT_CONTAINER:
2886 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2887 break;
2888 case LY_STMT_LEAF:
2889 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2890 break;
2891 case LY_STMT_LEAF_LIST:
2892 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2893 break;
2894 case LY_STMT_LIST:
2895 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2896 break;
2897 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002898 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002899 break;
2900 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002901 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002902 return LY_EVALID;
2903 }
2904 }
2905 return LY_SUCCESS;
2906}
2907
2908/**
2909 * @brief Parse the container statement.
2910 *
2911 * @param[in] ctx parser context.
2912 * @param[in] stmt Source statement data from the parsed extension instance.
2913 * @param[in] parent Parent node to connect to (not into).
2914 * @param[in,out] siblings Siblings to add to.
2915 *
2916 * @return LY_ERR values.
2917 */
2918static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002919lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002920 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002921{
2922 struct lysp_node_container *cont;
2923
2924 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2925
2926 /* create new container structure */
2927 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2928
2929 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2930 cont->nodetype = LYS_CONTAINER;
2931 cont->parent = parent;
2932
2933 /* parse substatements */
2934 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2935 switch (child->kw) {
2936 case LY_STMT_CONFIG:
2937 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
2938 break;
2939 case LY_STMT_DESCRIPTION:
2940 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
2941 break;
2942 case LY_STMT_IF_FEATURE:
2943 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
2944 break;
2945 case LY_STMT_REFERENCE:
2946 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
2947 break;
2948 case LY_STMT_STATUS:
2949 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
2950 break;
2951 case LY_STMT_WHEN:
2952 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
2953 break;
2954 case LY_STMT_PRESENCE:
2955 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
2956 break;
2957 case LY_STMT_ANYDATA:
2958 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
2959 /* fall through */
2960 case LY_STMT_ANYXML:
2961 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
2962 break;
2963 case LY_STMT_CHOICE:
2964 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
2965 break;
2966 case LY_STMT_CONTAINER:
2967 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
2968 break;
2969 case LY_STMT_LEAF:
2970 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
2971 break;
2972 case LY_STMT_LEAF_LIST:
2973 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
2974 break;
2975 case LY_STMT_LIST:
2976 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
2977 break;
2978 case LY_STMT_USES:
2979 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
2980 break;
2981
2982 case LY_STMT_TYPEDEF:
2983 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
2984 break;
2985 case LY_STMT_MUST:
2986 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
2987 break;
2988 case LY_STMT_ACTION:
2989 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
2990 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
2991 break;
2992 case LY_STMT_GROUPING:
2993 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
2994 break;
2995 case LY_STMT_NOTIFICATION:
2996 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
2997 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
2998 break;
2999 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003000 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003001 break;
3002 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003003 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003004 return LY_EVALID;
3005 }
3006 }
3007
3008 return LY_SUCCESS;
3009}
3010
3011/**
3012 * @brief Parse the list statement.
3013 *
3014 * @param[in] ctx parser context.
3015 * @param[in] stmt Source statement data from the parsed extension instance.
3016 * @param[in] parent Parent node to connect to (not into).
3017 * @param[in,out] siblings Siblings to add to.
3018 *
3019 * @return LY_ERR values.
3020 */
3021static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003022lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003023 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003024{
3025 struct lysp_node_list *list;
3026
3027 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3028
3029 /* create new list structure */
3030 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3031
3032 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3033 list->nodetype = LYS_LIST;
3034 list->parent = parent;
3035
3036 /* parse substatements */
3037 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3038 switch (child->kw) {
3039 case LY_STMT_CONFIG:
3040 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3041 break;
3042 case LY_STMT_DESCRIPTION:
3043 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3044 break;
3045 case LY_STMT_IF_FEATURE:
3046 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3047 break;
3048 case LY_STMT_REFERENCE:
3049 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3050 break;
3051 case LY_STMT_STATUS:
3052 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3053 break;
3054 case LY_STMT_WHEN:
3055 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3056 break;
3057 case LY_STMT_KEY:
3058 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3059 break;
3060 case LY_STMT_MAX_ELEMENTS:
3061 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3062 break;
3063 case LY_STMT_MIN_ELEMENTS:
3064 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3065 break;
3066 case LY_STMT_ORDERED_BY:
3067 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3068 break;
3069 case LY_STMT_UNIQUE:
3070 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3071 break;
3072
3073 case LY_STMT_ANYDATA:
3074 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3075 /* fall through */
3076 case LY_STMT_ANYXML:
3077 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3078 break;
3079 case LY_STMT_CHOICE:
3080 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3081 break;
3082 case LY_STMT_CONTAINER:
3083 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3084 break;
3085 case LY_STMT_LEAF:
3086 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3087 break;
3088 case LY_STMT_LEAF_LIST:
3089 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3090 break;
3091 case LY_STMT_LIST:
3092 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3093 break;
3094 case LY_STMT_USES:
3095 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3096 break;
3097
3098 case LY_STMT_TYPEDEF:
3099 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3100 break;
3101 case LY_STMT_MUST:
3102 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3103 break;
3104 case LY_STMT_ACTION:
3105 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3106 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3107 break;
3108 case LY_STMT_GROUPING:
3109 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3110 break;
3111 case LY_STMT_NOTIFICATION:
3112 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3113 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3114 break;
3115 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003116 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003117 break;
3118 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003119 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003120 return LY_EVALID;
3121 }
3122 }
3123
3124 return LY_SUCCESS;
3125}
3126
Michal Vasko193dacd2022-10-13 08:43:05 +02003127/**
3128 * @brief Parse generic statement structure into a specific parsed-schema structure.
3129 *
3130 * @param[in] pctx Parse context of the @p stmt being processed.
3131 * @param[in] stmt Generic statement structure to process.
3132 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3133 * @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.
3134 * @return LY_ERR value.
3135 */
3136static LY_ERR
3137lysp_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 +02003138{
Radek Krejciad5963b2019-09-06 16:03:05 +02003139 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003140 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003141
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003142 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003143 case LY_STMT_NOTIFICATION:
3144 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3145 break;
3146 case LY_STMT_INPUT:
3147 case LY_STMT_OUTPUT: {
3148 struct lysp_node_action_inout *inout;
3149
3150 *result = inout = calloc(1, sizeof *inout);
3151 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3152 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3153 break;
3154 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003155 case LY_STMT_ACTION:
3156 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003157 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003158 break;
3159 case LY_STMT_ANYDATA:
3160 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003161 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003162 break;
3163 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003164 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003165 break;
3166 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003167 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003168 break;
3169 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003170 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003171 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003172 case LY_STMT_CONTAINER:
3173 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003174 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003175 case LY_STMT_GROUPING:
3176 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3177 break;
3178 case LY_STMT_LEAF:
3179 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3180 break;
3181 case LY_STMT_LEAF_LIST:
3182 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3183 break;
3184 case LY_STMT_LIST:
3185 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3186 break;
3187 case LY_STMT_USES:
3188 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3189 break;
3190 case LY_STMT_BASE:
3191 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3192 break;
3193 case LY_STMT_ARGUMENT:
3194 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003195 case LY_STMT_CONTACT:
3196 case LY_STMT_DESCRIPTION:
3197 case LY_STMT_ERROR_APP_TAG:
3198 case LY_STMT_ERROR_MESSAGE:
3199 case LY_STMT_KEY:
3200 case LY_STMT_NAMESPACE:
3201 case LY_STMT_ORGANIZATION:
3202 case LY_STMT_PRESENCE:
3203 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003204 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003205 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003206 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003207 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003208 case LY_STMT_BIT:
3209 case LY_STMT_ENUM:
3210 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3211 break;
3212 case LY_STMT_CONFIG:
3213 assert(*result);
3214 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003215 break;
3216 case LY_STMT_DEFAULT:
3217 case LY_STMT_IF_FEATURE:
3218 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003219 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3220 break;
3221 case LY_STMT_DEVIATE:
3222 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3223 break;
3224 case LY_STMT_DEVIATION:
3225 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3226 break;
3227 case LY_STMT_EXTENSION:
3228 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003229 break;
3230 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003231 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3232 break;
3233 case LY_STMT_FEATURE:
3234 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003235 break;
3236 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003237 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003238 break;
3239 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003240 case LY_STMT_RANGE: {
3241 struct lysp_restr *restr;
3242
3243 *result = restr = calloc(1, sizeof *restr);
3244 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3245
3246 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003247 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003248 }
3249 case LY_STMT_MUST:
3250 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3251 break;
3252 case LY_STMT_IDENTITY:
3253 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3254 break;
3255 case LY_STMT_IMPORT:
3256 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3257 break;
3258 case LY_STMT_INCLUDE:
3259 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003260 break;
3261 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003262 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003263 break;
3264 case LY_STMT_MAX_ELEMENTS:
3265 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003266 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003267 break;
3268 case LY_STMT_MIN_ELEMENTS:
3269 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003270 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003271 break;
3272 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003273 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003274 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003275 case LY_STMT_MODULE: {
3276 struct lysp_module *mod;
3277
3278 *result = mod = calloc(1, sizeof *mod);
3279 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3280 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003281 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003282 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003283 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003284 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003285 break;
3286 case LY_STMT_PATH: {
3287 const char *str_path = NULL;
3288
Michal Vasko193dacd2022-10-13 08:43:05 +02003289 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3290 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003291 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003292 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003293 break;
3294 }
3295 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003296 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003297 break;
3298 case LY_STMT_POSITION:
3299 case LY_STMT_VALUE:
3300 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003301 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003302 break;
3303 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003304 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003305 break;
3306 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003307 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003308 break;
3309 case LY_STMT_REQUIRE_INSTANCE:
3310 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003311 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3312 break;
3313 case LY_STMT_REVISION:
3314 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003315 break;
Michal Vasko69730152020-10-09 16:30:07 +02003316 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003317 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003318 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003319 case LY_STMT_SUBMODULE: {
3320 struct lysp_submodule *submod;
3321
3322 *result = submod = calloc(1, sizeof *submod);
3323 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3324 ret = lysp_stmt_submodule(pctx, stmt, submod);
3325 break;
3326 }
Radek Krejci335332a2019-09-05 13:03:35 +02003327 case LY_STMT_TYPE: {
3328 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003329
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003330 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003331 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3332 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003333 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003334 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003335 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003336 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003337 break;
3338 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003339 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3340 break;
3341 case LY_STMT_YANG_VERSION:
3342 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3343 break;
3344 case LY_STMT_YIN_ELEMENT:
3345 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003346 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003347 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003348 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003349 return LY_EINT;
3350 }
3351
Radek Krejciad5963b2019-09-06 16:03:05 +02003352 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003353}
Michal Vasko59892dd2022-05-13 11:02:30 +02003354
Michal Vasko193dacd2022-10-13 08:43:05 +02003355LY_ERR
3356lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003357{
Michal Vasko193dacd2022-10-13 08:43:05 +02003358 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003359
Michal Vasko193dacd2022-10-13 08:43:05 +02003360 if (!substmt->storage) {
3361 /* nothing to parse, ignored */
3362 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003363 }
3364
Michal Vasko193dacd2022-10-13 08:43:05 +02003365 switch (stmt->kw) {
3366 case LY_STMT_NOTIFICATION:
3367 case LY_STMT_INPUT:
3368 case LY_STMT_OUTPUT:
3369 case LY_STMT_ACTION:
3370 case LY_STMT_RPC:
3371 case LY_STMT_ANYDATA:
3372 case LY_STMT_ANYXML:
3373 case LY_STMT_AUGMENT:
3374 case LY_STMT_CASE:
3375 case LY_STMT_CHOICE:
3376 case LY_STMT_CONTAINER:
3377 case LY_STMT_GROUPING:
3378 case LY_STMT_LEAF:
3379 case LY_STMT_LEAF_LIST:
3380 case LY_STMT_LIST:
3381 case LY_STMT_USES: {
3382 struct lysp_node **pnodes_p, *pnode = NULL;
3383
3384 /* parse the node */
3385 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3386
3387 /* usually is a linked-list of all the parsed schema nodes */
3388 pnodes_p = substmt->storage;
3389 while (*pnodes_p) {
3390 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003391 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003392 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003393
3394 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003395 }
3396 case LY_STMT_BASE:
3397 case LY_STMT_BIT:
3398 case LY_STMT_DEFAULT:
3399 case LY_STMT_DEVIATE:
3400 case LY_STMT_DEVIATION:
3401 case LY_STMT_ENUM:
3402 case LY_STMT_EXTENSION:
3403 case LY_STMT_EXTENSION_INSTANCE:
3404 case LY_STMT_FEATURE:
3405 case LY_STMT_IDENTITY:
3406 case LY_STMT_IF_FEATURE:
3407 case LY_STMT_IMPORT:
3408 case LY_STMT_INCLUDE:
3409 case LY_STMT_MUST:
3410 case LY_STMT_PATTERN:
3411 case LY_STMT_REFINE:
3412 case LY_STMT_REVISION:
3413 case LY_STMT_TYPEDEF:
3414 case LY_STMT_UNIQUE:
3415 /* parse, sized array */
3416 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003417 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003418
3419 case LY_STMT_ARGUMENT:
3420 case LY_STMT_BELONGS_TO:
3421 case LY_STMT_CONTACT:
3422 case LY_STMT_DESCRIPTION:
3423 case LY_STMT_ERROR_APP_TAG:
3424 case LY_STMT_ERROR_MESSAGE:
3425 case LY_STMT_FRACTION_DIGITS:
3426 case LY_STMT_KEY:
3427 case LY_STMT_LENGTH:
3428 case LY_STMT_MANDATORY:
3429 case LY_STMT_MAX_ELEMENTS:
3430 case LY_STMT_MIN_ELEMENTS:
3431 case LY_STMT_MODIFIER:
3432 case LY_STMT_MODULE:
3433 case LY_STMT_NAMESPACE:
3434 case LY_STMT_ORGANIZATION:
3435 case LY_STMT_PATH:
3436 case LY_STMT_POSITION:
3437 case LY_STMT_PREFIX:
3438 case LY_STMT_PRESENCE:
3439 case LY_STMT_RANGE:
3440 case LY_STMT_REFERENCE:
3441 case LY_STMT_REQUIRE_INSTANCE:
3442 case LY_STMT_REVISION_DATE:
3443 case LY_STMT_SUBMODULE:
3444 case LY_STMT_TYPE:
3445 case LY_STMT_UNITS:
3446 case LY_STMT_VALUE:
3447 case LY_STMT_WHEN:
3448 case LY_STMT_YANG_VERSION:
3449 case LY_STMT_YIN_ELEMENT:
3450 /* single item */
3451 if (*(void **)substmt->storage) {
3452 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3453 rc = LY_EVALID;
3454 goto cleanup;
3455 }
3456
3457 /* parse */
3458 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003459 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003460
3461 case LY_STMT_CONFIG:
3462 /* single item */
3463 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3464 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3465 rc = LY_EVALID;
3466 goto cleanup;
3467 }
3468
3469 /* parse */
3470 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3471 break;
3472
3473 case LY_STMT_ORDERED_BY:
3474 /* single item */
3475 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3476 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3477 rc = LY_EVALID;
3478 goto cleanup;
3479 }
3480
3481 /* parse */
3482 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3483 break;
3484
3485 case LY_STMT_STATUS:
3486 /* single item */
3487 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3488 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3489 rc = LY_EVALID;
3490 goto cleanup;
3491 }
3492
3493 /* parse */
3494 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3495 break;
3496
Michal Vasko59892dd2022-05-13 11:02:30 +02003497 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003498 LOGINT(PARSER_CTX(pctx));
3499 rc = LY_EINT;
3500 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003501 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003502
3503cleanup:
3504 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003505}