blob: a5daeb77a07932bc88b90d31b1ed0e8e4ef74e41 [file] [log] [blame]
Radek Krejci335332a2019-09-05 13:03:35 +02001/**
Michal Vasko59892dd2022-05-13 11:02:30 +02002 * @file parser_common.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief libyang common parser functions.
Radek Krejci335332a2019-09-05 13:03:35 +02005 *
Michal Vasko59892dd2022-05-13 11:02:30 +02006 * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
Radek Krejci335332a2019-09-05 13:03:35 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Michal Vasko59892dd2022-05-13 11:02:30 +020015#define _GNU_SOURCE
16#define _POSIX_C_SOURCE 200809L /* strdup, strndup */
17
18#ifdef __APPLE__
19#define _DARWIN_C_SOURCE /* F_GETPATH */
20#endif
21
22#if defined (__NetBSD__) || defined (__OpenBSD__)
23/* realpath */
24#define _XOPEN_SOURCE 1
25#define _XOPEN_SOURCE_EXTENDED 1
26#endif
27
28#include "parser_internal.h"
29
Radek Krejci335332a2019-09-05 13:03:35 +020030#include <assert.h>
31#include <ctype.h>
32#include <errno.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020033#include <fcntl.h>
34#include <limits.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020035#include <stdint.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020036#include <stdio.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020037#include <stdlib.h>
38#include <string.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020039#include <unistd.h>
Radek Krejci335332a2019-09-05 13:03:35 +020040
Radek Krejci535ea9f2020-05-29 16:01:05 +020041#include "common.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020042#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020043#include "dict.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020044#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010045#include "log.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020046#include "parser_data.h"
Michal Vasko69730152020-10-09 16:30:07 +020047#include "path.h"
Michal Vaskob4750962022-10-06 15:33:35 +020048#include "plugins_exts/metadata.h"
Michal Vasko193dacd2022-10-13 08:43:05 +020049#include "schema_features.h"
Radek Krejci77114102021-03-10 15:21:57 +010050#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020051#include "tree.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020052#include "tree_data.h"
53#include "tree_data_internal.h"
Radek Krejci335332a2019-09-05 13:03:35 +020054#include "tree_schema.h"
55#include "tree_schema_internal.h"
56
Michal Vasko59892dd2022-05-13 11:02:30 +020057void
58lyd_ctx_free(struct lyd_ctx *lydctx)
59{
60 ly_set_erase(&lydctx->node_types, NULL);
61 ly_set_erase(&lydctx->meta_types, NULL);
62 ly_set_erase(&lydctx->node_when, NULL);
Michal Vasko135719f2022-08-25 12:18:17 +020063 ly_set_erase(&lydctx->ext_node, free);
Michal Vasko59892dd2022-05-13 11:02:30 +020064 ly_set_erase(&lydctx->ext_val, free);
65}
66
67LY_ERR
68lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op)
69{
70 const struct lyd_node *iter;
71
72 *op = NULL;
73
74 if (!parent) {
75 /* no parent, nothing to look for */
76 return LY_SUCCESS;
77 }
78
79 /* we need to find the operation node if it already exists */
80 for (iter = parent; iter; iter = lyd_parent(iter)) {
81 if (iter->schema && (iter->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
82 break;
83 }
84 }
85
86 if (!iter) {
87 /* no operation found */
88 return LY_SUCCESS;
89 }
90
Michal Vaskoe3ed7dc2022-11-30 11:39:44 +010091 if (!(int_opts & LYD_INTOPT_ANY)) {
92 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
93 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
94 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
95 return LY_EINVAL;
96 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
97 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
98 iter->schema->name);
99 return LY_EINVAL;
100 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
101 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
102 iter->schema->name);
103 return LY_EINVAL;
104 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
105 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
106 iter->schema->name);
107 return LY_EINVAL;
108 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200109 }
110
111 *op = (struct lyd_node *)iter;
112 return LY_SUCCESS;
113}
114
115LY_ERR
116lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
117{
118 LY_ERR rc = LY_SUCCESS;
119
120 LOG_LOCSET(snode, NULL, NULL, NULL);
121
122 if (lydctx->int_opts & LYD_INTOPT_ANY) {
123 /* nothing to check, everything is allowed */
124 goto cleanup;
125 }
126
127 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
128 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
129 rc = LY_EVALID;
130 goto cleanup;
131 }
132
133 if (snode->nodetype == LYS_RPC) {
134 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
135 if (lydctx->op_node) {
136 goto error_node_dup;
137 }
138 } else {
139 goto error_node_inval;
140 }
141 } else if (snode->nodetype == LYS_ACTION) {
142 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
143 if (lydctx->op_node) {
144 goto error_node_dup;
145 }
146 } else {
147 goto error_node_inval;
148 }
149 } else if (snode->nodetype == LYS_NOTIF) {
150 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
151 if (lydctx->op_node) {
152 goto error_node_dup;
153 }
154 } else {
155 goto error_node_inval;
156 }
157 }
158
159 /* success */
160 goto cleanup;
161
162error_node_dup:
163 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
164 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
165 lydctx->op_node->schema->name);
166 rc = LY_EVALID;
167 goto cleanup;
168
169error_node_inval:
170 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
171 snode->name);
172 rc = LY_EVALID;
173
174cleanup:
175 LOG_LOCBACK(1, 0, 0, 0);
176 return rc;
177}
178
179LY_ERR
180lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
181 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
182{
183 ly_bool incomplete;
184
185 LY_CHECK_RET(lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node));
186
187 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
188 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
189 }
190 return LY_SUCCESS;
191}
192
193LY_ERR
194lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
195 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
196 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
197{
198 ly_bool incomplete;
199 struct lyd_meta *first = NULL;
200
201 if (meta && *meta) {
202 /* remember the first metadata */
203 first = *meta;
204 }
205
206 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
207 hints, ctx_node, 0, &incomplete));
208
209 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
210 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
211 }
212
213 if (first) {
214 /* always return the first metadata */
215 *meta = first;
216 }
217
218 return LY_SUCCESS;
219}
220
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200221LY_ERR
222lyd_parse_check_keys(struct lyd_node *node)
223{
224 const struct lysc_node *skey = NULL;
225 const struct lyd_node *key;
226
227 assert(node->schema->nodetype == LYS_LIST);
228
229 key = lyd_child(node);
230 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
231 if (!key || (key->schema != skey)) {
232 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
233 return LY_EVALID;
234 }
235
236 key = key->next;
237 }
238
239 return LY_SUCCESS;
240}
241
242LY_ERR
243lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
244 struct lysc_ext_instance *ext)
245{
246 struct lyd_meta *meta2, *prev_meta = NULL;
247 struct lyd_ctx_ext_val *ext_val;
248
249 if (lysc_has_when(node->schema)) {
250 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
251 /* remember we need to evaluate this node's when */
252 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
253 }
254 }
255
256 LY_LIST_FOR(*meta, meta2) {
257 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
258 meta2->value.boolean) {
259 /* node is default according to the metadata */
260 node->flags |= LYD_DEFAULT;
261
262 /* delete the metadata */
263 if (prev_meta) {
264 prev_meta->next = meta2->next;
265 } else {
266 *meta = (*meta)->next;
267 }
268 lyd_free_meta_single(meta2);
269 break;
270 }
271
272 prev_meta = meta2;
273 }
274
275 if (ext) {
276 /* parsed for an extension */
277 node->flags |= LYD_EXT;
278
279 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
280 /* rememeber for validation */
281 ext_val = malloc(sizeof *ext_val);
282 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
283 ext_val->ext = ext;
284 ext_val->sibling = node;
285 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
286 }
287 }
288
289 return LY_SUCCESS;
290}
291
Michal Vasko193dacd2022-10-13 08:43:05 +0200292void
293lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
294{
295 char path[PATH_MAX];
296
297#ifndef __APPLE__
298 char proc_path[32];
299 int len;
300#endif
301
302 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
303 if (*filepath) {
304 /* filepath already set */
305 return;
306 }
307
308 switch (in->type) {
309 case LY_IN_FILEPATH:
310 if (realpath(in->method.fpath.filepath, path) != NULL) {
311 lydict_insert(ctx, path, 0, filepath);
312 } else {
313 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
314 }
315
316 break;
317 case LY_IN_FD:
318#ifdef __APPLE__
319 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
320 lydict_insert(ctx, path, 0, filepath);
321 }
322#elif defined _WIN32
323 HANDLE h = _get_osfhandle(in->method.fd);
324 FILE_NAME_INFO info;
325 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
326 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
327 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
328 lydict_insert(ctx, buf, len, filepath);
329 }
330#else
331 /* get URI if there is /proc */
332 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
333 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
334 lydict_insert(ctx, path, len, filepath);
335 }
336#endif
337 break;
338 case LY_IN_MEMORY:
339 case LY_IN_FILE:
340 /* nothing to do */
341 break;
342 default:
343 LOGINT(ctx);
344 break;
345 }
346}
347
Michal Vaskod0625d72022-10-06 15:02:50 +0200348static 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 +0100349 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200350static 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 +0100351 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200352static 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 +0100353 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200354static 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 +0100355 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200356static 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 +0100357 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200358static 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 +0100359 struct lysp_node **siblings);
360
Radek Krejci335332a2019-09-05 13:03:35 +0200361static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200362lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200363{
Radek Krejci857189e2020-09-01 13:26:36 +0200364 uint8_t prefix = 0;
365 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200366 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200367 size_t utf8_char_len;
368
369 while (*val) {
370 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200371 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200372
373 switch (val_type) {
374 case Y_IDENTIF_ARG:
375 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
376 break;
377 case Y_PREF_IDENTIF_ARG:
378 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
379 break;
380 case Y_STR_ARG:
381 case Y_MAYBE_STR_ARG:
382 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
383 break;
384 }
385 first = 0;
386 }
387
388 return LY_SUCCESS;
389}
390
391/**
392 * @brief Parse extension instance.
393 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100394 * @param[in] ctx parser context.
395 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100396 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200397 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
398 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200399 * @return LY_ERR values.
400 */
401static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200402lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200403 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200404{
405 struct lysp_ext_instance *e;
406
Michal Vaskob36053d2020-03-26 15:49:30 +0100407 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200408
409 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200410 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100411 e->parent_stmt = insubstmt;
412 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200413 e->parsed = NULL;
Radek Krejci335332a2019-09-05 13:03:35 +0200414 /* TODO (duplicate) e->child = stmt->child; */
415
416 /* get optional argument */
417 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200418 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200419 }
420
421 return LY_SUCCESS;
422}
423
424/**
425 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
426 * description, etc...
427 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100428 * @param[in] ctx parser context.
429 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200430 * @param[in] substmt_index Index of this substatement.
431 * @param[in,out] value Place to store the parsed value.
432 * @param[in] arg Type of the YANG keyword argument (of the value).
433 * @param[in,out] exts Extension instances to add to.
434 *
435 * @return LY_ERR values.
436 */
437static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200438lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
439 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200440{
Radek Krejci335332a2019-09-05 13:03:35 +0200441 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200442 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200443 return LY_EVALID;
444 }
445
446 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200447 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200448
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100449 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
450 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200451 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100452 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200453 break;
454 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200455 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200456 return LY_EVALID;
457 }
458 }
459 return LY_SUCCESS;
460}
461
462/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200463 * @brief Parse a qname that can have more instances such as if-feature.
464 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100465 * @param[in] ctx parser context.
466 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200467 * @param[in,out] qnames Parsed qnames to add to.
468 * @param[in] arg Type of the expected argument.
469 * @param[in,out] exts Extension instances to add to.
470 *
471 * @return LY_ERR values.
472 */
473static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200474lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
475 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200476{
477 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200478
479 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
480
481 /* allocate new pointer */
482 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
483 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100484 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200485
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100486 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
487 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200488 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100489 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200490 break;
491 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200492 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200493 return LY_EVALID;
494 }
495 }
496 return LY_SUCCESS;
497}
498
499/**
Radek Krejci335332a2019-09-05 13:03:35 +0200500 * @brief Parse a generic text field that can have more instances such as base.
501 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100502 * @param[in] ctx parser context.
503 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200504 * @param[in,out] texts Parsed values to add to.
505 * @param[in] arg Type of the expected argument.
506 * @param[in,out] exts Extension instances to add to.
507 *
508 * @return LY_ERR values.
509 */
510static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200511lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
512 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200513{
514 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200515
516 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
517
518 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100519 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200520 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200521
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100522 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
523 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200524 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100525 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200526 break;
527 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200528 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200529 return LY_EVALID;
530 }
531 }
532 return LY_SUCCESS;
533}
534
535/**
536 * @brief Parse the status statement.
537 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100538 * @param[in] ctx parser context.
539 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200540 * @param[in,out] flags Flags to add to.
541 * @param[in,out] exts Extension instances to add to.
542 *
543 * @return LY_ERR values.
544 */
545static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200546lysp_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 +0200547{
548 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200549
550 if (*flags & LYS_STATUS_MASK) {
551 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
552 return LY_EVALID;
553 }
554
555 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
556 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100557 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200558 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100559 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200560 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100561 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200562 *flags |= LYS_STATUS_OBSLT;
563 } else {
564 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
565 return LY_EVALID;
566 }
567
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100568 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
569 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200570 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100571 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200572 break;
573 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200574 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200575 return LY_EVALID;
576 }
577 }
578 return LY_SUCCESS;
579}
580
581/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100582 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200583 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100584 * @param[in] ctx parser context.
585 * @param[in] stmt Source statement data from the parsed extension instance.
586 * @param[in,out] when_p When pointer to parse to.
587 *
588 * @return LY_ERR values.
589 */
590static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200591lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100592{
593 LY_ERR ret = LY_SUCCESS;
594 struct lysp_when *when;
595
596 if (*when_p) {
597 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
598 return LY_EVALID;
599 }
600
601 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
602
603 when = calloc(1, sizeof *when);
604 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
605 *when_p = when;
606
607 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
608
609 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
610 switch (child->kw) {
611 case LY_STMT_DESCRIPTION:
612 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
613 break;
614 case LY_STMT_REFERENCE:
615 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
616 break;
617 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100618 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100619 break;
620 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200621 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100622 return LY_EVALID;
623 }
624 }
625 return ret;
626}
627
628/**
629 * @brief Parse the config statement.
630 *
631 * @param[in] ctx parser context.
632 * @param[in] stmt Source statement data from the parsed extension instance.
633 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200634 * @param[in,out] exts Extension instances to add to.
635 *
636 * @return LY_ERR values.
637 */
638static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200639lysp_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 +0200640{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100641 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200642
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100643 if (*flags & LYS_CONFIG_MASK) {
644 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
645 return LY_EVALID;
646 }
647
648 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
649 arg_len = strlen(stmt->arg);
650 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
651 *flags |= LYS_CONFIG_W;
652 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
653 *flags |= LYS_CONFIG_R;
654 } else {
655 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
656 return LY_EVALID;
657 }
658
659 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
660 switch (child->kw) {
661 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100662 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100663 break;
664 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200665 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100666 return LY_EVALID;
667 }
668 }
669
670 return LY_SUCCESS;
671}
672
673/**
674 * @brief Parse the mandatory statement.
675 *
676 * @param[in] ctx parser context.
677 * @param[in] stmt Source statement data from the parsed extension instance.
678 * @param[in,out] flags Flags to add to.
679 * @param[in,out] exts Extension instances to add to.
680 *
681 * @return LY_ERR values.
682 */
683static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200684lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200685 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100686{
687 size_t arg_len;
688
689 if (*flags & LYS_MAND_MASK) {
690 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
691 return LY_EVALID;
692 }
693
694 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
695 arg_len = strlen(stmt->arg);
696 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
697 *flags |= LYS_MAND_TRUE;
698 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
699 *flags |= LYS_MAND_FALSE;
700 } else {
701 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
702 return LY_EVALID;
703 }
704
705 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
706 switch (child->kw) {
707 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100708 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100709 break;
710 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200711 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100712 return LY_EVALID;
713 }
714 }
715
716 return LY_SUCCESS;
717}
718
719/**
720 * @brief Parse a restriction such as range or length.
721 *
722 * @param[in] ctx parser context.
723 * @param[in] stmt Source statement data from the parsed extension instance.
724 * @param[in,out] exts Extension instances to add to.
725 *
726 * @return LY_ERR values.
727 */
728static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200729lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100730{
Radek Krejci335332a2019-09-05 13:03:35 +0200731 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200732 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100733 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200734
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100735 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
736 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200737 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100738 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200739 break;
740 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100741 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200742 break;
743 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100744 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200745 break;
746 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100747 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200748 break;
749 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100750 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200751 break;
752 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200753 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200754 return LY_EVALID;
755 }
756 }
757 return LY_SUCCESS;
758}
759
760/**
761 * @brief Parse a restriction that can have more instances such as must.
762 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100763 * @param[in] ctx parser context.
764 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200765 * @param[in,out] restrs Restrictions to add to.
766 *
767 * @return LY_ERR values.
768 */
769static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200770lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200771{
772 struct lysp_restr *restr;
773
Michal Vaskob36053d2020-03-26 15:49:30 +0100774 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100775 return lysp_stmt_restr(ctx, stmt, restr);
776}
777
778/**
779 * @brief Parse the anydata or anyxml statement.
780 *
781 * @param[in] ctx parser context.
782 * @param[in] stmt Source statement data from the parsed extension instance.
783 * @param[in,out] siblings Siblings to add to.
784 *
785 * @return LY_ERR values.
786 */
787static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200788lysp_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 +0100789{
790 struct lysp_node_anydata *any;
791
792 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
793
794 /* create new structure and insert into siblings */
795 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
796
797 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
798 any->parent = parent;
799
800 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
801
802 /* parse substatements */
803 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
804 switch (child->kw) {
805 case LY_STMT_CONFIG:
806 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
807 break;
808 case LY_STMT_DESCRIPTION:
809 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
810 break;
811 case LY_STMT_IF_FEATURE:
812 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
813 break;
814 case LY_STMT_MANDATORY:
815 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
816 break;
817 case LY_STMT_MUST:
818 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
819 break;
820 case LY_STMT_REFERENCE:
821 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
822 break;
823 case LY_STMT_STATUS:
824 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
825 break;
826 case LY_STMT_WHEN:
827 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
828 break;
829 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100830 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100831 break;
832 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200833 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
834 (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 +0100835 return LY_EVALID;
836 }
837 }
838
839 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200840}
841
842/**
843 * @brief Parse the value or position statement. Substatement of type enum statement.
844 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100845 * @param[in] ctx parser context.
846 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200847 * @param[in,out] value Value to write to.
848 * @param[in,out] flags Flags to write to.
849 * @param[in,out] exts Extension instances to add to.
850 *
851 * @return LY_ERR values.
852 */
853static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200854lysp_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 +0200855 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200856{
857 size_t arg_len;
858 char *ptr = NULL;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200859 long long int num = 0;
860 unsigned long long int unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200861
862 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200863 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200864 return LY_EVALID;
865 }
866 *flags |= LYS_SET_VALUE;
867
868 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
869
870 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100871 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
872 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200873 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200874 goto error;
875 }
876
877 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100878 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200879 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200880 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200881 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200882 goto error;
883 }
884 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200885 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200886 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200887 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200888 goto error;
889 }
890 }
891 /* we have not parsed the whole argument */
892 if ((size_t)(ptr - stmt->arg) != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200893 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200894 goto error;
895 }
896 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200897 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200898 goto error;
899 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100900 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200901 *value = num;
902 } else {
903 *value = unum;
904 }
905
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100906 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
907 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200908 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100909 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 +0200910 break;
911 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200912 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200913 return LY_EVALID;
914 }
915 }
916 return LY_SUCCESS;
917
918error:
919 return LY_EVALID;
920}
921
922/**
923 * @brief Parse the enum or bit statement. Substatement of type statement.
924 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100925 * @param[in] ctx parser context.
926 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200927 * @param[in,out] enums Enums or bits to add to.
928 *
929 * @return LY_ERR values.
930 */
931static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200932lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +0200933{
934 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200935
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100936 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 +0200937
Michal Vaskob36053d2020-03-26 15:49:30 +0100938 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200939
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100940 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +0200941 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
942 } /* else nothing specific for YANG_BIT */
943
Radek Krejci011e4aa2020-09-04 15:22:31 +0200944 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +0200945 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +0200946
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100947 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
948 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200949 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100950 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200951 break;
952 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +0200953 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100954 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200955 break;
956 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100957 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200958 break;
959 case LY_STMT_STATUS:
960 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
961 break;
962 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +0200963 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
964 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100965 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200966 break;
967 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +0200968 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
969 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100970 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200971 break;
972 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100973 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200974 break;
975 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200976 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200977 return LY_EVALID;
978 }
979 }
Michal Vasko193dacd2022-10-13 08:43:05 +0200980
Radek Krejci335332a2019-09-05 13:03:35 +0200981 return LY_SUCCESS;
982}
983
984/**
985 * @brief Parse the fraction-digits statement. Substatement of type statement.
986 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100987 * @param[in] ctx parser context.
988 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200989 * @param[in,out] fracdig Value to write to.
990 * @param[in,out] exts Extension instances to add to.
991 *
992 * @return LY_ERR values.
993 */
994static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200995lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +0200996 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200997{
998 char *ptr;
999 size_t arg_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001000 unsigned long long int num;
Radek Krejci335332a2019-09-05 13:03:35 +02001001
1002 if (*fracdig) {
1003 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1004 return LY_EVALID;
1005 }
1006
1007 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1008 arg_len = strlen(stmt->arg);
1009 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1010 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1011 return LY_EVALID;
1012 }
1013
1014 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001015 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001016 /* we have not parsed the whole argument */
1017 if ((size_t)(ptr - stmt->arg) != arg_len) {
1018 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1019 return LY_EVALID;
1020 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001021 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001022 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1023 return LY_EVALID;
1024 }
1025 *fracdig = num;
1026
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001027 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1028 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001029 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001030 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001031 break;
1032 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001033 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001034 return LY_EVALID;
1035 }
1036 }
1037 return LY_SUCCESS;
1038}
1039
1040/**
1041 * @brief Parse the require-instance statement. Substatement of type statement.
1042 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001043 * @param[in] ctx parser context.
1044 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001045 * @param[in,out] reqinst Value to write to.
1046 * @param[in,out] flags Flags to write to.
1047 * @param[in,out] exts Extension instances to add to.
1048 *
1049 * @return LY_ERR values.
1050 */
1051static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001052lysp_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 +02001053 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001054{
1055 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001056
1057 if (*flags & LYS_SET_REQINST) {
1058 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1059 return LY_EVALID;
1060 }
1061 *flags |= LYS_SET_REQINST;
1062
1063 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1064 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001065 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001066 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001067 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001068 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1069 return LY_EVALID;
1070 }
1071
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001072 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1073 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001074 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001075 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001076 break;
1077 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001078 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001079 return LY_EVALID;
1080 }
1081 }
1082 return LY_SUCCESS;
1083}
1084
1085/**
1086 * @brief Parse the modifier statement. Substatement of type pattern statement.
1087 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001088 * @param[in] ctx parser context.
1089 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001090 * @param[in,out] pat Value to write to.
1091 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001092 * @return LY_ERR values.
1093 */
1094static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001095lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001096 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001097{
1098 size_t arg_len;
1099 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001100
Radek Krejcif13b87b2020-12-01 22:02:17 +01001101 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001102 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1103 return LY_EVALID;
1104 }
1105
1106 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1107 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001108 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001109 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1110 return LY_EVALID;
1111 }
1112
1113 /* replace the value in the dictionary */
1114 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001115 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001116 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001117 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001118
Radek Krejcif13b87b2020-12-01 22:02:17 +01001119 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1120 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001121 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001122
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001123 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1124 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001125 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001126 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001127 break;
1128 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001129 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001130 return LY_EVALID;
1131 }
1132 }
1133 return LY_SUCCESS;
1134}
1135
1136/**
1137 * @brief Parse the pattern statement. Substatement of type statement.
1138 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001139 * @param[in] ctx parser context.
1140 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001141 * @param[in,out] patterns Restrictions to add to.
1142 *
1143 * @return LY_ERR values.
1144 */
1145static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001146lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001147{
1148 char *buf;
1149 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001150 struct lysp_restr *restr;
1151
1152 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001153 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001154 arg_len = strlen(stmt->arg);
1155
1156 /* add special meaning first byte */
1157 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001158 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001159 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001160 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001161 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001162 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001163 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001164
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001165 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1166 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001167 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001168 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001169 break;
1170 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001171 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001172 break;
1173 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001174 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001175 break;
1176 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001177 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001178 break;
1179 case LY_STMT_MODIFIER:
1180 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001181 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001182 break;
1183 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001184 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001185 break;
1186 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001187 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001188 return LY_EVALID;
1189 }
1190 }
1191 return LY_SUCCESS;
1192}
1193
1194/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001195 * @brief Parse the deviate statement. Substatement of deviation statement.
1196 *
1197 * @param[in] ctx parser context.
1198 * @param[in] stmt Source statement data from the parsed extension instance.
1199 * @param[in,out] devs Array of deviates to add to.
1200 * @param[in,out] exts Extension instances to add to.
1201 * @return LY_ERR values.
1202 */
1203static LY_ERR
1204lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1205{
1206 (void)stmt;
1207 (void)devs;
1208 (void)exts;
1209
1210 /* TODO */
1211 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1212 return LY_EINVAL;
1213}
1214
1215/**
1216 * @brief Parse the deviation statement.
1217 *
1218 * @param[in] ctx parser context.
1219 * @param[in] stmt Source statement data from the parsed extension instance.
1220 * @param[in,out] deviations Array of deviations to add to.
1221 * @return LY_ERR values.
1222 */
1223static LY_ERR
1224lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1225{
1226 struct lysp_deviation *dev;
1227
1228 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1229
1230 /* store nodeid */
1231 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1232 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1233
1234 /* parse substatements */
1235 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1236 switch (child->kw) {
1237 case LY_STMT_DESCRIPTION:
1238 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1239 break;
1240 case LY_STMT_DEVIATE:
1241 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1242 break;
1243 case LY_STMT_REFERENCE:
1244 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1245 break;
1246 case LY_STMT_EXTENSION_INSTANCE:
1247 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1248 break;
1249 default:
1250 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1251 return LY_EVALID;
1252 }
1253 }
1254
1255 return LY_SUCCESS;
1256}
1257
1258/**
1259 * @brief Parse the yang-version statement.
1260 *
1261 * @param[in] ctx parser context.
1262 * @param[in] stmt Source statement data from the parsed extension instance.
1263 * @param[out] version Version to write to.
1264 * @param[in,out] exts Extension instances to add to.
1265 * @return LY_ERR values.
1266 */
1267static LY_ERR
1268lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1269{
1270 if (*version) {
1271 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1272 return LY_EVALID;
1273 }
1274
1275 /* store flag */
1276 if (!strcmp(stmt->arg, "1")) {
1277 *version = LYS_VERSION_1_0;
1278 } else if (!strcmp(stmt->arg, "1.1")) {
1279 *version = LYS_VERSION_1_1;
1280 } else {
1281 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yang-version");
1282 return LY_EVALID;
1283 }
1284
1285 /* parse substatements */
1286 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1287 switch (child->kw) {
1288 case LY_STMT_EXTENSION_INSTANCE:
1289 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1290 break;
1291 default:
1292 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1293 return LY_EVALID;
1294 }
1295 }
1296
1297 return LY_SUCCESS;
1298}
1299
1300/**
1301 * @brief Parse the module statement.
1302 *
1303 * @param[in] ctx parser context.
1304 * @param[in] stmt Source statement data from the parsed extension instance.
1305 * @param[in,out] mod Module to fill.
1306 * @return LY_ERR values.
1307 */
1308static LY_ERR
1309lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1310{
1311 (void)stmt;
1312 (void)mod;
1313
1314 /* TODO */
1315 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1316 return LY_EINVAL;
1317}
1318
1319/**
1320 * @brief Parse the submodule statement.
1321 *
1322 * @param[in] ctx parser context.
1323 * @param[in] stmt Source statement data from the parsed extension instance.
1324 * @param[in,out] submod Module to fill.
1325 * @return LY_ERR values.
1326 */
1327static LY_ERR
1328lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1329{
1330 (void)stmt;
1331 (void)submod;
1332
1333 /* TODO */
1334 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1335 return LY_EINVAL;
1336}
1337
1338/**
1339 * @brief Parse the yin-element statement. Substatement of argument statement.
1340 *
1341 * @param[in] ctx parser context.
1342 * @param[in] stmt Source statement data from the parsed extension instance.
1343 * @param[in,out] flags Flags to write to.
1344 * @param[in,out] exts Extension instances to add to.
1345 * @return LY_ERR values.
1346 */
1347static LY_ERR
1348lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1349{
1350 if (*flags & LYS_YINELEM_MASK) {
1351 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1352 return LY_EVALID;
1353 }
1354
1355 /* store flag */
1356 if (!strcmp(stmt->arg, "true")) {
1357 *flags |= LYS_YINELEM_TRUE;
1358 } else if (!strcmp(stmt->arg, "false")) {
1359 *flags |= LYS_YINELEM_FALSE;
1360 } else {
1361 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yin-element");
1362 return LY_EVALID;
1363 }
1364
1365 /* parse substatements */
1366 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1367 switch (child->kw) {
1368 case LY_STMT_EXTENSION_INSTANCE:
1369 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1370 break;
1371 default:
1372 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1373 return LY_EVALID;
1374 }
1375 }
1376
1377 return LY_SUCCESS;
1378}
1379
1380/**
1381 * @brief Parse the argument statement. Substatement of extension statement.
1382 *
1383 * @param[in] ctx parser context.
1384 * @param[in] stmt Source statement data from the parsed extension instance.
1385 * @param[in,out] ex Extension to fill.
1386 * @return LY_ERR values.
1387 */
1388static LY_ERR
1389lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1390{
1391 if (ex->argname) {
1392 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1393 return LY_EVALID;
1394 }
1395
1396 /* store argument name */
1397 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1398 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1399
1400 /* parse substatements */
1401 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1402 switch (child->kw) {
1403 case LY_STMT_YIN_ELEMENT:
1404 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1405 break;
1406 case LY_STMT_EXTENSION_INSTANCE:
1407 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1408 break;
1409 default:
1410 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1411 return LY_EVALID;
1412 }
1413 }
1414
1415 return LY_SUCCESS;
1416}
1417
1418/**
1419 * @brief Parse the extension statement.
1420 *
1421 * @param[in] ctx parser context.
1422 * @param[in] stmt Source statement data from the parsed extension instance.
1423 * @param[in,out] extensions Array of extensions to add to.
1424 * @return LY_ERR values.
1425 */
1426static LY_ERR
1427lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1428{
1429 struct lysp_ext *ex;
1430
1431 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1432
1433 /* store name */
1434 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1435 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1436
1437 /* parse substatements */
1438 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1439 switch (child->kw) {
1440 case LY_STMT_DESCRIPTION:
1441 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1442 break;
1443 case LY_STMT_REFERENCE:
1444 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1445 break;
1446 case LY_STMT_STATUS:
1447 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1448 break;
1449 case LY_STMT_ARGUMENT:
1450 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1451 break;
1452 case LY_STMT_EXTENSION_INSTANCE:
1453 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1454 break;
1455 default:
1456 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1457 return LY_EVALID;
1458 }
1459 }
1460
1461 return LY_SUCCESS;
1462}
1463
1464/**
1465 * @brief Parse the feature statement.
1466 *
1467 * @param[in] ctx parser context.
1468 * @param[in] stmt Source statement data from the parsed extension instance.
1469 * @param[in,out] features Array of features to add to.
1470 * @return LY_ERR values.
1471 */
1472static LY_ERR
1473lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1474{
1475 struct lysp_feature *feat;
1476
1477 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1478
1479 /* store name */
1480 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1481 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1482
1483 /* parse substatements */
1484 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1485 switch (child->kw) {
1486 case LY_STMT_DESCRIPTION:
1487 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1488 break;
1489 case LY_STMT_IF_FEATURE:
1490 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1491 break;
1492 case LY_STMT_REFERENCE:
1493 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1494 break;
1495 case LY_STMT_STATUS:
1496 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1497 break;
1498 case LY_STMT_EXTENSION_INSTANCE:
1499 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1500 break;
1501 default:
1502 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1503 return LY_EVALID;
1504 }
1505 }
1506
1507 return LY_SUCCESS;
1508}
1509
1510/**
1511 * @brief Parse the identity statement.
1512 *
1513 * @param[in] ctx parser context.
1514 * @param[in] stmt Source statement data from the parsed extension instance.
1515 * @param[in,out] identities Array of identities to add to.
1516 * @return LY_ERR values.
1517 */
1518static LY_ERR
1519lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1520{
1521 struct lysp_ident *ident;
1522
1523 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1524
1525 /* store name */
1526 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1527 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1528
1529 /* parse substatements */
1530 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1531 switch (child->kw) {
1532 case LY_STMT_DESCRIPTION:
1533 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1534 break;
1535 case LY_STMT_IF_FEATURE:
1536 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1537 break;
1538 case LY_STMT_REFERENCE:
1539 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1540 break;
1541 case LY_STMT_STATUS:
1542 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1543 break;
1544 case LY_STMT_BASE:
1545 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1546 break;
1547 case LY_STMT_EXTENSION_INSTANCE:
1548 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1549 break;
1550 default:
1551 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1552 return LY_EVALID;
1553 }
1554 }
1555
1556 return LY_SUCCESS;
1557}
1558
1559/**
1560 * @brief Parse the import statement.
1561 *
1562 * @param[in] ctx parser context.
1563 * @param[in] stmt Source statement data from the parsed extension instance.
1564 * @param[in,out] imports Array of imports to add to.
1565 * @return LY_ERR values.
1566 */
1567static LY_ERR
1568lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1569{
1570 struct lysp_import *imp;
1571 const char *str = NULL;
1572
1573 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1574
1575 /* store name */
1576 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1577 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1578
1579 /* parse substatements */
1580 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1581 switch (child->kw) {
1582 case LY_STMT_PREFIX:
1583 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1584 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1585 break;
1586 case LY_STMT_DESCRIPTION:
1587 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1588 break;
1589 case LY_STMT_REFERENCE:
1590 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1591 break;
1592 case LY_STMT_REVISION_DATE:
1593 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1594 strcpy(imp->rev, str);
1595 lydict_remove(PARSER_CTX(ctx), str);
1596 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1597 break;
1598 case LY_STMT_EXTENSION_INSTANCE:
1599 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1600 break;
1601 default:
1602 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1603 return LY_EVALID;
1604 }
1605 }
1606
1607 return LY_SUCCESS;
1608}
1609
1610/**
1611 * @brief Parse the include statement.
1612 *
1613 * @param[in] ctx parser context.
1614 * @param[in] stmt Source statement data from the parsed extension instance.
1615 * @param[in,out] includes Array of identities to add to.
1616 * @return LY_ERR values.
1617 */
1618static LY_ERR
1619lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1620{
1621 struct lysp_include *inc;
1622 const char *str = NULL;
1623
1624 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1625
1626 /* store name */
1627 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1628 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1629
1630 /* parse substatements */
1631 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1632 switch (child->kw) {
1633 case LY_STMT_DESCRIPTION:
1634 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1635 break;
1636 case LY_STMT_REFERENCE:
1637 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1638 break;
1639 case LY_STMT_REVISION_DATE:
1640 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1641 strcpy(inc->rev, str);
1642 lydict_remove(PARSER_CTX(ctx), str);
1643 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1644 break;
1645 case LY_STMT_EXTENSION_INSTANCE:
1646 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1647 break;
1648 default:
1649 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1650 return LY_EVALID;
1651 }
1652 }
1653
1654 return LY_SUCCESS;
1655}
1656
1657/**
1658 * @brief Parse the revision statement.
1659 *
1660 * @param[in] ctx parser context.
1661 * @param[in] stmt Source statement data from the parsed extension instance.
1662 * @param[in,out] includes Array of identities to add to.
1663 * @return LY_ERR values.
1664 */
1665static LY_ERR
1666lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1667{
1668 struct lysp_revision *rev;
1669
1670 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1671
1672 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001673 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001674 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001675
1676 /* parse substatements */
1677 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1678 switch (child->kw) {
1679 case LY_STMT_DESCRIPTION:
1680 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1681 break;
1682 case LY_STMT_REFERENCE:
1683 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1684 break;
1685 case LY_STMT_EXTENSION_INSTANCE:
1686 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1687 break;
1688 default:
1689 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1690 return LY_EVALID;
1691 }
1692 }
1693
1694 return LY_SUCCESS;
1695}
1696
1697/**
Radek Krejci335332a2019-09-05 13:03:35 +02001698 * @brief Parse the type statement.
1699 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001700 * @param[in] ctx parser context.
1701 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001702 * @param[in,out] type Type to wrote to.
1703 *
1704 * @return LY_ERR values.
1705 */
1706static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001707lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001708{
1709 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001710 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001711 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001712
1713 if (type->name) {
1714 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1715 return LY_EVALID;
1716 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001717
1718 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001719 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001720 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001721
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001722 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1723 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001724 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001725 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001726 type->flags |= LYS_SET_BASE;
1727 break;
1728 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001729 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001730 type->flags |= LYS_SET_BIT;
1731 break;
1732 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001733 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001734 type->flags |= LYS_SET_ENUM;
1735 break;
1736 case LY_STMT_FRACTION_DIGITS:
1737 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1738 type->flags |= LYS_SET_FRDIGITS;
1739 break;
1740 case LY_STMT_LENGTH:
1741 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001742 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001743 return LY_EVALID;
1744 }
1745 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001746 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001747
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001748 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001749 type->flags |= LYS_SET_LENGTH;
1750 break;
1751 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001752 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001753 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001754 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001755 lydict_remove(PARSER_CTX(ctx), str_path);
1756 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001757 type->flags |= LYS_SET_PATH;
1758 break;
1759 case LY_STMT_PATTERN:
1760 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1761 type->flags |= LYS_SET_PATTERN;
1762 break;
1763 case LY_STMT_RANGE:
1764 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001765 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001766 return LY_EVALID;
1767 }
1768 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001769 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001770
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001771 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001772 type->flags |= LYS_SET_RANGE;
1773 break;
1774 case LY_STMT_REQUIRE_INSTANCE:
1775 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001776 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001777 break;
1778 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001779 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001780 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1781 type->flags |= LYS_SET_TYPE;
1782 break;
1783 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001784 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001785 break;
1786 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001787 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001788 return LY_EVALID;
1789 }
1790 }
1791 return LY_SUCCESS;
1792}
1793
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001794/**
1795 * @brief Parse the leaf statement.
1796 *
1797 * @param[in] ctx parser context.
1798 * @param[in] stmt Source statement data from the parsed extension instance.
1799 * @param[in] parent Parent node to connect to (not into).
1800 * @param[in,out] siblings Siblings to add to.
1801 *
1802 * @return LY_ERR values.
1803 */
1804static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001805lysp_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 +01001806{
1807 struct lysp_node_leaf *leaf;
1808
1809 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1810
1811 /* create new leaf structure */
1812 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1813 leaf->nodetype = LYS_LEAF;
1814 leaf->parent = parent;
1815
1816 /* get name */
1817 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1818
1819 /* parse substatements */
1820 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1821 switch (child->kw) {
1822 case LY_STMT_CONFIG:
1823 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1824 break;
1825 case LY_STMT_DEFAULT:
1826 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 +01001827 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001828 break;
1829 case LY_STMT_DESCRIPTION:
1830 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1831 break;
1832 case LY_STMT_IF_FEATURE:
1833 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1834 break;
1835 case LY_STMT_MANDATORY:
1836 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1837 break;
1838 case LY_STMT_MUST:
1839 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1840 break;
1841 case LY_STMT_REFERENCE:
1842 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1843 break;
1844 case LY_STMT_STATUS:
1845 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1846 break;
1847 case LY_STMT_TYPE:
1848 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1849 break;
1850 case LY_STMT_UNITS:
1851 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1852 break;
1853 case LY_STMT_WHEN:
1854 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1855 break;
1856 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001857 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001858 break;
1859 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001860 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001861 return LY_EVALID;
1862 }
1863 }
1864
1865 /* mandatory substatements */
1866 if (!leaf->type.name) {
1867 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1868 return LY_EVALID;
1869 }
1870
1871 return LY_SUCCESS;
1872}
1873
1874/**
1875 * @brief Parse the max-elements statement.
1876 *
1877 * @param[in] ctx parser context.
1878 * @param[in] stmt Source statement data from the parsed extension instance.
1879 * @param[in,out] max Value to write to.
1880 * @param[in,out] flags Flags to write to.
1881 * @param[in,out] exts Extension instances to add to.
1882 *
1883 * @return LY_ERR values.
1884 */
1885static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001886lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
1887 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001888{
1889 size_t arg_len;
1890 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001891 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001892
1893 if (*flags & LYS_SET_MAX) {
1894 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1895 return LY_EVALID;
1896 }
1897 *flags |= LYS_SET_MAX;
1898
1899 /* get value */
1900 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1901 arg_len = strlen(stmt->arg);
1902
1903 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1904 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1905 return LY_EVALID;
1906 }
1907
1908 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1909 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001910 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001911 /* we have not parsed the whole argument */
1912 if ((size_t)(ptr - stmt->arg) != arg_len) {
1913 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1914 return LY_EVALID;
1915 }
1916 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1917 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1918 return LY_EVALID;
1919 }
1920
1921 *max = num;
1922 } else {
1923 /* unbounded */
1924 *max = 0;
1925 }
1926
1927 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1928 switch (child->kw) {
1929 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001930 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001931 break;
1932 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001933 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001934 return LY_EVALID;
1935 }
1936 }
1937
1938 return LY_SUCCESS;
1939}
1940
1941/**
1942 * @brief Parse the min-elements statement.
1943 *
1944 * @param[in] ctx parser context.
1945 * @param[in] stmt Source statement data from the parsed extension instance.
1946 * @param[in,out] min Value to write to.
1947 * @param[in,out] flags Flags to write to.
1948 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001949 * @return LY_ERR values.
1950 */
1951static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001952lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
1953 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001954{
1955 size_t arg_len;
1956 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001957 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001958
1959 if (*flags & LYS_SET_MIN) {
1960 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
1961 return LY_EVALID;
1962 }
1963 *flags |= LYS_SET_MIN;
1964
1965 /* get value */
1966 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1967 arg_len = strlen(stmt->arg);
1968
1969 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
1970 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1971 return LY_EVALID;
1972 }
1973
1974 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001975 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001976 /* we have not parsed the whole argument */
1977 if ((size_t)(ptr - stmt->arg) != arg_len) {
1978 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1979 return LY_EVALID;
1980 }
1981 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1982 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
1983 return LY_EVALID;
1984 }
1985 *min = num;
1986
1987 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1988 switch (child->kw) {
1989 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001990 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001991 break;
1992 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001993 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001994 return LY_EVALID;
1995 }
1996 }
1997
1998 return LY_SUCCESS;
1999}
2000
2001/**
2002 * @brief Parse the ordered-by statement.
2003 *
2004 * @param[in] ctx parser context.
2005 * @param[in] stmt Source statement data from the parsed extension instance.
2006 * @param[in,out] flags Flags to write to.
2007 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002008 * @return LY_ERR values.
2009 */
2010static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002011lysp_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 +01002012{
2013 size_t arg_len;
2014
2015 if (*flags & LYS_ORDBY_MASK) {
2016 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2017 return LY_EVALID;
2018 }
2019
2020 /* get value */
2021 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2022 arg_len = strlen(stmt->arg);
2023 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2024 *flags |= LYS_MAND_TRUE;
2025 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2026 *flags |= LYS_MAND_FALSE;
2027 } else {
2028 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2029 return LY_EVALID;
2030 }
2031
2032 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2033 switch (child->kw) {
2034 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002035 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002036 break;
2037 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002038 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002039 return LY_EVALID;
2040 }
2041 }
2042
2043 return LY_SUCCESS;
2044}
2045
2046/**
2047 * @brief Parse the leaf-list statement.
2048 *
2049 * @param[in] ctx parser context.
2050 * @param[in] stmt Source statement data from the parsed extension instance.
2051 * @param[in] parent Parent node to connect to (not into).
2052 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002053 * @return LY_ERR values.
2054 */
2055static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002056lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002057 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002058{
2059 struct lysp_node_leaflist *llist;
2060
2061 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2062
2063 /* create new leaf-list structure */
2064 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2065 llist->nodetype = LYS_LEAFLIST;
2066 llist->parent = parent;
2067
2068 /* get name */
2069 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2070
2071 /* parse substatements */
2072 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2073 switch (child->kw) {
2074 case LY_STMT_CONFIG:
2075 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2076 break;
2077 case LY_STMT_DEFAULT:
2078 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2079 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2080 break;
2081 case LY_STMT_DESCRIPTION:
2082 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2083 break;
2084 case LY_STMT_IF_FEATURE:
2085 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2086 break;
2087 case LY_STMT_MAX_ELEMENTS:
2088 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2089 break;
2090 case LY_STMT_MIN_ELEMENTS:
2091 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2092 break;
2093 case LY_STMT_MUST:
2094 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2095 break;
2096 case LY_STMT_ORDERED_BY:
2097 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2098 break;
2099 case LY_STMT_REFERENCE:
2100 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2101 break;
2102 case LY_STMT_STATUS:
2103 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2104 break;
2105 case LY_STMT_TYPE:
2106 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2107 break;
2108 case LY_STMT_UNITS:
2109 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2110 break;
2111 case LY_STMT_WHEN:
2112 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2113 break;
2114 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002115 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002116 break;
2117 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002118 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002119 return LY_EVALID;
2120 }
2121 }
2122
2123 /* mandatory substatements */
2124 if (!llist->type.name) {
2125 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2126 return LY_EVALID;
2127 }
2128
2129 return LY_SUCCESS;
2130}
2131
2132/**
2133 * @brief Parse the refine statement.
2134 *
2135 * @param[in] ctx parser context.
2136 * @param[in] stmt Source statement data from the parsed extension instance.
2137 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002138 * @return LY_ERR values.
2139 */
2140static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002141lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002142{
2143 struct lysp_refine *rf;
2144
2145 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2146
2147 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2148
2149 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2150
2151 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2152 switch (child->kw) {
2153 case LY_STMT_CONFIG:
2154 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2155 break;
2156 case LY_STMT_DEFAULT:
2157 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2158 break;
2159 case LY_STMT_DESCRIPTION:
2160 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2161 break;
2162 case LY_STMT_IF_FEATURE:
2163 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2164 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2165 break;
2166 case LY_STMT_MAX_ELEMENTS:
2167 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2168 break;
2169 case LY_STMT_MIN_ELEMENTS:
2170 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2171 break;
2172 case LY_STMT_MUST:
2173 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2174 break;
2175 case LY_STMT_MANDATORY:
2176 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2177 break;
2178 case LY_STMT_REFERENCE:
2179 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2180 break;
2181 case LY_STMT_PRESENCE:
2182 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2183 break;
2184 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002185 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002186 break;
2187 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002188 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002189 return LY_EVALID;
2190 }
2191 }
2192
2193 return LY_SUCCESS;
2194}
2195
2196/**
2197 * @brief Parse the typedef statement.
2198 *
2199 * @param[in] ctx parser context.
2200 * @param[in] stmt Source statement data from the parsed extension instance.
2201 * @param[in] parent Parent node to connect to (not into).
2202 * @param[in,out] typedefs Typedefs to add to.
2203 *
2204 * @return LY_ERR values.
2205 */
2206static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002207lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002208 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002209{
2210 struct lysp_tpdf *tpdf;
2211
2212 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2213
2214 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2215
2216 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2217
2218 /* parse substatements */
2219 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2220 switch (child->kw) {
2221 case LY_STMT_DEFAULT:
2222 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 +01002223 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002224 break;
2225 case LY_STMT_DESCRIPTION:
2226 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2227 break;
2228 case LY_STMT_REFERENCE:
2229 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2230 break;
2231 case LY_STMT_STATUS:
2232 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2233 break;
2234 case LY_STMT_TYPE:
2235 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2236 break;
2237 case LY_STMT_UNITS:
2238 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2239 break;
2240 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002241 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002242 break;
2243 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002244 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002245 return LY_EVALID;
2246 }
2247 }
2248
2249 /* mandatory substatements */
2250 if (!tpdf->type.name) {
2251 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2252 return LY_EVALID;
2253 }
2254
2255 /* store data for collision check */
2256 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2257 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2258 }
2259
2260 return LY_SUCCESS;
2261}
2262
2263/**
2264 * @brief Parse the input or output statement.
2265 *
2266 * @param[in] ctx parser context.
2267 * @param[in] stmt Source statement data from the parsed extension instance.
2268 * @param[in] parent Parent node to connect to (not into).
2269 * @param[in,out] inout_p Input/output pointer to write to.
2270 *
2271 * @return LY_ERR values.
2272 */
2273static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002274lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002275 struct lysp_node_action_inout *inout_p)
2276{
2277 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002278 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002279 return LY_EVALID;
2280 }
2281
2282 /* initiate structure */
2283 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2284 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2285 inout_p->parent = parent;
2286
2287 /* parse substatements */
2288 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2289 switch (child->kw) {
2290 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002291 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002292 /* fall through */
2293 case LY_STMT_ANYXML:
2294 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2295 break;
2296 case LY_STMT_CHOICE:
2297 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2298 break;
2299 case LY_STMT_CONTAINER:
2300 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2301 break;
2302 case LY_STMT_LEAF:
2303 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2304 break;
2305 case LY_STMT_LEAF_LIST:
2306 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2307 break;
2308 case LY_STMT_LIST:
2309 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2310 break;
2311 case LY_STMT_USES:
2312 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2313 break;
2314 case LY_STMT_TYPEDEF:
2315 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2316 break;
2317 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002318 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002319 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2320 break;
2321 case LY_STMT_GROUPING:
2322 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2323 break;
2324 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002325 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002326 break;
2327 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002328 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002329 return LY_EVALID;
2330 }
2331 }
2332
2333 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002334 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002335 return LY_EVALID;
2336 }
2337
2338 return LY_SUCCESS;
2339}
2340
2341/**
2342 * @brief Parse the action statement.
2343 *
2344 * @param[in] ctx parser context.
2345 * @param[in] stmt Source statement data from the parsed extension instance.
2346 * @param[in] parent Parent node to connect to (not into).
2347 * @param[in,out] actions Actions to add to.
2348 *
2349 * @return LY_ERR values.
2350 */
2351static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002352lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002353 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002354{
2355 struct lysp_node_action *act;
2356
2357 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2358
2359 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2360
2361 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2362 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2363 act->parent = parent;
2364
2365 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2366 switch (child->kw) {
2367 case LY_STMT_DESCRIPTION:
2368 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2369 break;
2370 case LY_STMT_IF_FEATURE:
2371 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2372 break;
2373 case LY_STMT_REFERENCE:
2374 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2375 break;
2376 case LY_STMT_STATUS:
2377 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2378 break;
2379
2380 case LY_STMT_INPUT:
2381 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2382 break;
2383 case LY_STMT_OUTPUT:
2384 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2385 break;
2386
2387 case LY_STMT_TYPEDEF:
2388 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2389 break;
2390 case LY_STMT_GROUPING:
2391 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2392 break;
2393 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002394 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 +01002395 break;
2396 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002397 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002398 return LY_EVALID;
2399 }
2400 }
2401
2402 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2403 if (!act->input.nodetype) {
2404 act->input.nodetype = LYS_INPUT;
2405 act->input.parent = &act->node;
2406 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2407 }
2408 if (!act->output.nodetype) {
2409 act->output.nodetype = LYS_OUTPUT;
2410 act->output.parent = &act->node;
2411 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2412 }
2413
2414 return LY_SUCCESS;
2415}
2416
2417/**
2418 * @brief Parse the notification statement.
2419 *
2420 * @param[in] ctx parser context.
2421 * @param[in] stmt Source statement data from the parsed extension instance.
2422 * @param[in] parent Parent node to connect to (not into).
2423 * @param[in,out] notifs Notifications to add to.
2424 *
2425 * @return LY_ERR values.
2426 */
2427static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002428lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002429 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002430{
2431 struct lysp_node_notif *notif;
2432
2433 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2434
2435 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2436
2437 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2438 notif->nodetype = LYS_NOTIF;
2439 notif->parent = parent;
2440
2441 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2442 switch (child->kw) {
2443 case LY_STMT_DESCRIPTION:
2444 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2445 break;
2446 case LY_STMT_IF_FEATURE:
2447 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2448 break;
2449 case LY_STMT_REFERENCE:
2450 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2451 break;
2452 case LY_STMT_STATUS:
2453 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2454 break;
2455
2456 case LY_STMT_ANYDATA:
2457 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2458 /* fall through */
2459 case LY_STMT_ANYXML:
2460 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2461 break;
2462 case LY_STMT_CHOICE:
2463 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2464 break;
2465 case LY_STMT_CONTAINER:
2466 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2467 break;
2468 case LY_STMT_LEAF:
2469 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2470 break;
2471 case LY_STMT_LEAF_LIST:
2472 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2473 break;
2474 case LY_STMT_LIST:
2475 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2476 break;
2477 case LY_STMT_USES:
2478 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2479 break;
2480
2481 case LY_STMT_MUST:
2482 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2483 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2484 break;
2485 case LY_STMT_TYPEDEF:
2486 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2487 break;
2488 case LY_STMT_GROUPING:
2489 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2490 break;
2491 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002492 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002493 break;
2494 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002495 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002496 return LY_EVALID;
2497 }
2498 }
2499
2500 return LY_SUCCESS;
2501}
2502
2503/**
2504 * @brief Parse the grouping statement.
2505 *
2506 * @param[in] ctx parser context.
2507 * @param[in] stmt Source statement data from the parsed extension instance.
2508 * @param[in] parent Parent node to connect to (not into).
2509 * @param[in,out] groupings Groupings to add to.
2510 *
2511 * @return LY_ERR values.
2512 */
2513static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002514lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002515 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002516{
2517 struct lysp_node_grp *grp;
2518
2519 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2520
2521 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2522
2523 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2524 grp->nodetype = LYS_GROUPING;
2525 grp->parent = parent;
2526
2527 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2528 switch (child->kw) {
2529 case LY_STMT_DESCRIPTION:
2530 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2531 break;
2532 case LY_STMT_REFERENCE:
2533 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2534 break;
2535 case LY_STMT_STATUS:
2536 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2537 break;
2538
2539 case LY_STMT_ANYDATA:
2540 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2541 /* fall through */
2542 case LY_STMT_ANYXML:
2543 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2544 break;
2545 case LY_STMT_CHOICE:
2546 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2547 break;
2548 case LY_STMT_CONTAINER:
2549 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2550 break;
2551 case LY_STMT_LEAF:
2552 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2553 break;
2554 case LY_STMT_LEAF_LIST:
2555 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2556 break;
2557 case LY_STMT_LIST:
2558 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2559 break;
2560 case LY_STMT_USES:
2561 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2562 break;
2563
2564 case LY_STMT_TYPEDEF:
2565 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2566 break;
2567 case LY_STMT_ACTION:
2568 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2569 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2570 break;
2571 case LY_STMT_GROUPING:
2572 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2573 break;
2574 case LY_STMT_NOTIFICATION:
2575 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2576 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2577 break;
2578 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002579 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002580 break;
2581 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002582 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002583 return LY_EVALID;
2584 }
2585 }
2586
2587 return LY_SUCCESS;
2588}
2589
2590/**
2591 * @brief Parse the augment statement.
2592 *
2593 * @param[in] ctx parser context.
2594 * @param[in] stmt Source statement data from the parsed extension instance.
2595 * @param[in] parent Parent node to connect to (not into).
2596 * @param[in,out] augments Augments to add to.
2597 *
2598 * @return LY_ERR values.
2599 */
2600static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002601lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002602 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002603{
2604 struct lysp_node_augment *aug;
2605
2606 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2607
2608 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2609
2610 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2611 aug->nodetype = LYS_AUGMENT;
2612 aug->parent = parent;
2613
2614 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2615 switch (child->kw) {
2616 case LY_STMT_DESCRIPTION:
2617 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2618 break;
2619 case LY_STMT_IF_FEATURE:
2620 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2621 break;
2622 case LY_STMT_REFERENCE:
2623 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2624 break;
2625 case LY_STMT_STATUS:
2626 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2627 break;
2628 case LY_STMT_WHEN:
2629 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2630 break;
2631
2632 case LY_STMT_ANYDATA:
2633 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2634 /* fall through */
2635 case LY_STMT_ANYXML:
2636 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2637 break;
2638 case LY_STMT_CASE:
2639 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2640 break;
2641 case LY_STMT_CHOICE:
2642 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2643 break;
2644 case LY_STMT_CONTAINER:
2645 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2646 break;
2647 case LY_STMT_LEAF:
2648 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2649 break;
2650 case LY_STMT_LEAF_LIST:
2651 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2652 break;
2653 case LY_STMT_LIST:
2654 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2655 break;
2656 case LY_STMT_USES:
2657 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2658 break;
2659
2660 case LY_STMT_ACTION:
2661 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2662 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2663 break;
2664 case LY_STMT_NOTIFICATION:
2665 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2666 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2667 break;
2668 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002669 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002670 break;
2671 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002672 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002673 return LY_EVALID;
2674 }
2675 }
2676
2677 return LY_SUCCESS;
2678}
2679
2680/**
2681 * @brief Parse the uses statement.
2682 *
2683 * @param[in] ctx parser context.
2684 * @param[in] stmt Source statement data from the parsed extension instance.
2685 * @param[in] parent Parent node to connect to (not into).
2686 * @param[in,out] siblings Siblings to add to.
2687 *
2688 * @return LY_ERR values.
2689 */
2690static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002691lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002692 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002693{
2694 struct lysp_node_uses *uses;
2695
2696 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2697
2698 /* create uses structure */
2699 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2700
2701 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2702 uses->nodetype = LYS_USES;
2703 uses->parent = parent;
2704
2705 /* parse substatements */
2706 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2707 switch (child->kw) {
2708 case LY_STMT_DESCRIPTION:
2709 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2710 break;
2711 case LY_STMT_IF_FEATURE:
2712 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2713 break;
2714 case LY_STMT_REFERENCE:
2715 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2716 break;
2717 case LY_STMT_STATUS:
2718 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2719 break;
2720 case LY_STMT_WHEN:
2721 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2722 break;
2723
2724 case LY_STMT_REFINE:
2725 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2726 break;
2727 case LY_STMT_AUGMENT:
2728 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2729 break;
2730 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002731 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002732 break;
2733 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002734 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002735 return LY_EVALID;
2736 }
2737 }
2738
2739 return LY_SUCCESS;
2740}
2741
2742/**
2743 * @brief Parse the case statement.
2744 *
2745 * @param[in] ctx parser context.
2746 * @param[in] stmt Source statement data from the parsed extension instance.
2747 * @param[in] parent Parent node to connect to (not into).
2748 * @param[in,out] siblings Siblings to add to.
2749 *
2750 * @return LY_ERR values.
2751 */
2752static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002753lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002754 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002755{
2756 struct lysp_node_case *cas;
2757
2758 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2759
2760 /* create new case structure */
2761 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2762
2763 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2764 cas->nodetype = LYS_CASE;
2765 cas->parent = parent;
2766
2767 /* parse substatements */
2768 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2769 switch (child->kw) {
2770 case LY_STMT_DESCRIPTION:
2771 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2772 break;
2773 case LY_STMT_IF_FEATURE:
2774 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2775 break;
2776 case LY_STMT_REFERENCE:
2777 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2778 break;
2779 case LY_STMT_STATUS:
2780 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2781 break;
2782 case LY_STMT_WHEN:
2783 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2784 break;
2785
2786 case LY_STMT_ANYDATA:
2787 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2788 /* fall through */
2789 case LY_STMT_ANYXML:
2790 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2791 break;
2792 case LY_STMT_CHOICE:
2793 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2794 break;
2795 case LY_STMT_CONTAINER:
2796 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2797 break;
2798 case LY_STMT_LEAF:
2799 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2800 break;
2801 case LY_STMT_LEAF_LIST:
2802 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2803 break;
2804 case LY_STMT_LIST:
2805 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2806 break;
2807 case LY_STMT_USES:
2808 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2809 break;
2810 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002811 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002812 break;
2813 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002814 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002815 return LY_EVALID;
2816 }
2817 }
2818 return LY_SUCCESS;
2819}
2820
2821/**
2822 * @brief Parse the choice statement.
2823 *
2824 * @param[in] ctx parser context.
2825 * @param[in] stmt Source statement data from the parsed extension instance.
2826 * @param[in] parent Parent node to connect to (not into).
2827 * @param[in,out] siblings Siblings to add to.
2828 *
2829 * @return LY_ERR values.
2830 */
2831static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002832lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002833 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002834{
2835 struct lysp_node_choice *choice;
2836
2837 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2838
2839 /* create new choice structure */
2840 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2841
2842 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2843 choice->nodetype = LYS_CHOICE;
2844 choice->parent = parent;
2845
2846 /* parse substatements */
2847 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2848 switch (child->kw) {
2849 case LY_STMT_CONFIG:
2850 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2851 break;
2852 case LY_STMT_DESCRIPTION:
2853 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2854 break;
2855 case LY_STMT_IF_FEATURE:
2856 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2857 break;
2858 case LY_STMT_MANDATORY:
2859 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2860 break;
2861 case LY_STMT_REFERENCE:
2862 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2863 break;
2864 case LY_STMT_STATUS:
2865 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2866 break;
2867 case LY_STMT_WHEN:
2868 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2869 break;
2870 case LY_STMT_DEFAULT:
2871 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 +01002872 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002873 break;
2874 case LY_STMT_ANYDATA:
2875 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2876 /* fall through */
2877 case LY_STMT_ANYXML:
2878 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2879 break;
2880 case LY_STMT_CASE:
2881 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2882 break;
2883 case LY_STMT_CHOICE:
2884 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2885 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2886 break;
2887 case LY_STMT_CONTAINER:
2888 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2889 break;
2890 case LY_STMT_LEAF:
2891 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2892 break;
2893 case LY_STMT_LEAF_LIST:
2894 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2895 break;
2896 case LY_STMT_LIST:
2897 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2898 break;
2899 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002900 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002901 break;
2902 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002903 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002904 return LY_EVALID;
2905 }
2906 }
2907 return LY_SUCCESS;
2908}
2909
2910/**
2911 * @brief Parse the container statement.
2912 *
2913 * @param[in] ctx parser context.
2914 * @param[in] stmt Source statement data from the parsed extension instance.
2915 * @param[in] parent Parent node to connect to (not into).
2916 * @param[in,out] siblings Siblings to add to.
2917 *
2918 * @return LY_ERR values.
2919 */
2920static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002921lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002922 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002923{
2924 struct lysp_node_container *cont;
2925
2926 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2927
2928 /* create new container structure */
2929 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2930
2931 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2932 cont->nodetype = LYS_CONTAINER;
2933 cont->parent = parent;
2934
2935 /* parse substatements */
2936 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2937 switch (child->kw) {
2938 case LY_STMT_CONFIG:
2939 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
2940 break;
2941 case LY_STMT_DESCRIPTION:
2942 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
2943 break;
2944 case LY_STMT_IF_FEATURE:
2945 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
2946 break;
2947 case LY_STMT_REFERENCE:
2948 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
2949 break;
2950 case LY_STMT_STATUS:
2951 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
2952 break;
2953 case LY_STMT_WHEN:
2954 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
2955 break;
2956 case LY_STMT_PRESENCE:
2957 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
2958 break;
2959 case LY_STMT_ANYDATA:
2960 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
2961 /* fall through */
2962 case LY_STMT_ANYXML:
2963 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
2964 break;
2965 case LY_STMT_CHOICE:
2966 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
2967 break;
2968 case LY_STMT_CONTAINER:
2969 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
2970 break;
2971 case LY_STMT_LEAF:
2972 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
2973 break;
2974 case LY_STMT_LEAF_LIST:
2975 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
2976 break;
2977 case LY_STMT_LIST:
2978 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
2979 break;
2980 case LY_STMT_USES:
2981 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
2982 break;
2983
2984 case LY_STMT_TYPEDEF:
2985 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
2986 break;
2987 case LY_STMT_MUST:
2988 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
2989 break;
2990 case LY_STMT_ACTION:
2991 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
2992 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
2993 break;
2994 case LY_STMT_GROUPING:
2995 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
2996 break;
2997 case LY_STMT_NOTIFICATION:
2998 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
2999 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3000 break;
3001 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003002 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003003 break;
3004 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003005 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003006 return LY_EVALID;
3007 }
3008 }
3009
3010 return LY_SUCCESS;
3011}
3012
3013/**
3014 * @brief Parse the list statement.
3015 *
3016 * @param[in] ctx parser context.
3017 * @param[in] stmt Source statement data from the parsed extension instance.
3018 * @param[in] parent Parent node to connect to (not into).
3019 * @param[in,out] siblings Siblings to add to.
3020 *
3021 * @return LY_ERR values.
3022 */
3023static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003024lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003025 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003026{
3027 struct lysp_node_list *list;
3028
3029 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3030
3031 /* create new list structure */
3032 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3033
3034 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3035 list->nodetype = LYS_LIST;
3036 list->parent = parent;
3037
3038 /* parse substatements */
3039 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3040 switch (child->kw) {
3041 case LY_STMT_CONFIG:
3042 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3043 break;
3044 case LY_STMT_DESCRIPTION:
3045 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3046 break;
3047 case LY_STMT_IF_FEATURE:
3048 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3049 break;
3050 case LY_STMT_REFERENCE:
3051 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3052 break;
3053 case LY_STMT_STATUS:
3054 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3055 break;
3056 case LY_STMT_WHEN:
3057 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3058 break;
3059 case LY_STMT_KEY:
3060 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3061 break;
3062 case LY_STMT_MAX_ELEMENTS:
3063 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3064 break;
3065 case LY_STMT_MIN_ELEMENTS:
3066 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3067 break;
3068 case LY_STMT_ORDERED_BY:
3069 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3070 break;
3071 case LY_STMT_UNIQUE:
3072 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3073 break;
3074
3075 case LY_STMT_ANYDATA:
3076 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3077 /* fall through */
3078 case LY_STMT_ANYXML:
3079 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3080 break;
3081 case LY_STMT_CHOICE:
3082 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3083 break;
3084 case LY_STMT_CONTAINER:
3085 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3086 break;
3087 case LY_STMT_LEAF:
3088 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3089 break;
3090 case LY_STMT_LEAF_LIST:
3091 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3092 break;
3093 case LY_STMT_LIST:
3094 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3095 break;
3096 case LY_STMT_USES:
3097 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3098 break;
3099
3100 case LY_STMT_TYPEDEF:
3101 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3102 break;
3103 case LY_STMT_MUST:
3104 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3105 break;
3106 case LY_STMT_ACTION:
3107 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3108 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3109 break;
3110 case LY_STMT_GROUPING:
3111 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3112 break;
3113 case LY_STMT_NOTIFICATION:
3114 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3115 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3116 break;
3117 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003118 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003119 break;
3120 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003121 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003122 return LY_EVALID;
3123 }
3124 }
3125
3126 return LY_SUCCESS;
3127}
3128
Michal Vasko193dacd2022-10-13 08:43:05 +02003129/**
3130 * @brief Parse generic statement structure into a specific parsed-schema structure.
3131 *
3132 * @param[in] pctx Parse context of the @p stmt being processed.
3133 * @param[in] stmt Generic statement structure to process.
3134 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3135 * @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.
3136 * @return LY_ERR value.
3137 */
3138static LY_ERR
3139lysp_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 +02003140{
Radek Krejciad5963b2019-09-06 16:03:05 +02003141 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003142 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003143
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003144 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003145 case LY_STMT_NOTIFICATION:
3146 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3147 break;
3148 case LY_STMT_INPUT:
3149 case LY_STMT_OUTPUT: {
3150 struct lysp_node_action_inout *inout;
3151
3152 *result = inout = calloc(1, sizeof *inout);
3153 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3154 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3155 break;
3156 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003157 case LY_STMT_ACTION:
3158 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003159 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003160 break;
3161 case LY_STMT_ANYDATA:
3162 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003163 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003164 break;
3165 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003166 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003167 break;
3168 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003169 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003170 break;
3171 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003172 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003173 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003174 case LY_STMT_CONTAINER:
3175 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003176 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003177 case LY_STMT_GROUPING:
3178 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3179 break;
3180 case LY_STMT_LEAF:
3181 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3182 break;
3183 case LY_STMT_LEAF_LIST:
3184 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3185 break;
3186 case LY_STMT_LIST:
3187 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3188 break;
3189 case LY_STMT_USES:
3190 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3191 break;
3192 case LY_STMT_BASE:
3193 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3194 break;
3195 case LY_STMT_ARGUMENT:
3196 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003197 case LY_STMT_CONTACT:
3198 case LY_STMT_DESCRIPTION:
3199 case LY_STMT_ERROR_APP_TAG:
3200 case LY_STMT_ERROR_MESSAGE:
3201 case LY_STMT_KEY:
3202 case LY_STMT_NAMESPACE:
3203 case LY_STMT_ORGANIZATION:
3204 case LY_STMT_PRESENCE:
3205 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003206 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003207 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003208 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003209 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003210 case LY_STMT_BIT:
3211 case LY_STMT_ENUM:
3212 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3213 break;
3214 case LY_STMT_CONFIG:
3215 assert(*result);
3216 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003217 break;
3218 case LY_STMT_DEFAULT:
3219 case LY_STMT_IF_FEATURE:
3220 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003221 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3222 break;
3223 case LY_STMT_DEVIATE:
3224 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3225 break;
3226 case LY_STMT_DEVIATION:
3227 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3228 break;
3229 case LY_STMT_EXTENSION:
3230 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003231 break;
3232 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003233 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3234 break;
3235 case LY_STMT_FEATURE:
3236 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003237 break;
3238 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003239 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003240 break;
3241 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003242 case LY_STMT_RANGE: {
3243 struct lysp_restr *restr;
3244
3245 *result = restr = calloc(1, sizeof *restr);
3246 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3247
3248 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003249 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003250 }
3251 case LY_STMT_MUST:
3252 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3253 break;
3254 case LY_STMT_IDENTITY:
3255 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3256 break;
3257 case LY_STMT_IMPORT:
3258 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3259 break;
3260 case LY_STMT_INCLUDE:
3261 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003262 break;
3263 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003264 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003265 break;
3266 case LY_STMT_MAX_ELEMENTS:
3267 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003268 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003269 break;
3270 case LY_STMT_MIN_ELEMENTS:
3271 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003272 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003273 break;
3274 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003275 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003276 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003277 case LY_STMT_MODULE: {
3278 struct lysp_module *mod;
3279
3280 *result = mod = calloc(1, sizeof *mod);
3281 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3282 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003283 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003284 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003285 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003286 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003287 break;
3288 case LY_STMT_PATH: {
3289 const char *str_path = NULL;
3290
Michal Vasko193dacd2022-10-13 08:43:05 +02003291 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3292 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003293 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003294 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003295 break;
3296 }
3297 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003298 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003299 break;
3300 case LY_STMT_POSITION:
3301 case LY_STMT_VALUE:
3302 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003303 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003304 break;
3305 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003306 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003307 break;
3308 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003309 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003310 break;
3311 case LY_STMT_REQUIRE_INSTANCE:
3312 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003313 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3314 break;
3315 case LY_STMT_REVISION:
3316 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003317 break;
Michal Vasko69730152020-10-09 16:30:07 +02003318 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003319 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003320 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003321 case LY_STMT_SUBMODULE: {
3322 struct lysp_submodule *submod;
3323
3324 *result = submod = calloc(1, sizeof *submod);
3325 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3326 ret = lysp_stmt_submodule(pctx, stmt, submod);
3327 break;
3328 }
Radek Krejci335332a2019-09-05 13:03:35 +02003329 case LY_STMT_TYPE: {
3330 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003331
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003332 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003333 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3334 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003335 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003336 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003337 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003338 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003339 break;
3340 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003341 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3342 break;
3343 case LY_STMT_YANG_VERSION:
3344 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3345 break;
3346 case LY_STMT_YIN_ELEMENT:
3347 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003348 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003349 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003350 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003351 return LY_EINT;
3352 }
3353
Radek Krejciad5963b2019-09-06 16:03:05 +02003354 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003355}
Michal Vasko59892dd2022-05-13 11:02:30 +02003356
Michal Vasko193dacd2022-10-13 08:43:05 +02003357LY_ERR
3358lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003359{
Michal Vasko193dacd2022-10-13 08:43:05 +02003360 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003361
Michal Vasko193dacd2022-10-13 08:43:05 +02003362 if (!substmt->storage) {
3363 /* nothing to parse, ignored */
3364 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003365 }
3366
Michal Vasko193dacd2022-10-13 08:43:05 +02003367 switch (stmt->kw) {
3368 case LY_STMT_NOTIFICATION:
3369 case LY_STMT_INPUT:
3370 case LY_STMT_OUTPUT:
3371 case LY_STMT_ACTION:
3372 case LY_STMT_RPC:
3373 case LY_STMT_ANYDATA:
3374 case LY_STMT_ANYXML:
3375 case LY_STMT_AUGMENT:
3376 case LY_STMT_CASE:
3377 case LY_STMT_CHOICE:
3378 case LY_STMT_CONTAINER:
3379 case LY_STMT_GROUPING:
3380 case LY_STMT_LEAF:
3381 case LY_STMT_LEAF_LIST:
3382 case LY_STMT_LIST:
3383 case LY_STMT_USES: {
3384 struct lysp_node **pnodes_p, *pnode = NULL;
3385
3386 /* parse the node */
3387 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3388
3389 /* usually is a linked-list of all the parsed schema nodes */
3390 pnodes_p = substmt->storage;
3391 while (*pnodes_p) {
3392 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003393 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003394 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003395
3396 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003397 }
3398 case LY_STMT_BASE:
3399 case LY_STMT_BIT:
3400 case LY_STMT_DEFAULT:
3401 case LY_STMT_DEVIATE:
3402 case LY_STMT_DEVIATION:
3403 case LY_STMT_ENUM:
3404 case LY_STMT_EXTENSION:
3405 case LY_STMT_EXTENSION_INSTANCE:
3406 case LY_STMT_FEATURE:
3407 case LY_STMT_IDENTITY:
3408 case LY_STMT_IF_FEATURE:
3409 case LY_STMT_IMPORT:
3410 case LY_STMT_INCLUDE:
3411 case LY_STMT_MUST:
3412 case LY_STMT_PATTERN:
3413 case LY_STMT_REFINE:
3414 case LY_STMT_REVISION:
3415 case LY_STMT_TYPEDEF:
3416 case LY_STMT_UNIQUE:
3417 /* parse, sized array */
3418 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003419 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003420
3421 case LY_STMT_ARGUMENT:
3422 case LY_STMT_BELONGS_TO:
3423 case LY_STMT_CONTACT:
3424 case LY_STMT_DESCRIPTION:
3425 case LY_STMT_ERROR_APP_TAG:
3426 case LY_STMT_ERROR_MESSAGE:
3427 case LY_STMT_FRACTION_DIGITS:
3428 case LY_STMT_KEY:
3429 case LY_STMT_LENGTH:
3430 case LY_STMT_MANDATORY:
3431 case LY_STMT_MAX_ELEMENTS:
3432 case LY_STMT_MIN_ELEMENTS:
3433 case LY_STMT_MODIFIER:
3434 case LY_STMT_MODULE:
3435 case LY_STMT_NAMESPACE:
3436 case LY_STMT_ORGANIZATION:
3437 case LY_STMT_PATH:
3438 case LY_STMT_POSITION:
3439 case LY_STMT_PREFIX:
3440 case LY_STMT_PRESENCE:
3441 case LY_STMT_RANGE:
3442 case LY_STMT_REFERENCE:
3443 case LY_STMT_REQUIRE_INSTANCE:
3444 case LY_STMT_REVISION_DATE:
3445 case LY_STMT_SUBMODULE:
3446 case LY_STMT_TYPE:
3447 case LY_STMT_UNITS:
3448 case LY_STMT_VALUE:
3449 case LY_STMT_WHEN:
3450 case LY_STMT_YANG_VERSION:
3451 case LY_STMT_YIN_ELEMENT:
3452 /* single item */
3453 if (*(void **)substmt->storage) {
3454 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3455 rc = LY_EVALID;
3456 goto cleanup;
3457 }
3458
3459 /* parse */
3460 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003461 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003462
3463 case LY_STMT_CONFIG:
3464 /* single item */
3465 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3466 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3467 rc = LY_EVALID;
3468 goto cleanup;
3469 }
3470
3471 /* parse */
3472 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3473 break;
3474
3475 case LY_STMT_ORDERED_BY:
3476 /* single item */
3477 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3478 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3479 rc = LY_EVALID;
3480 goto cleanup;
3481 }
3482
3483 /* parse */
3484 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3485 break;
3486
3487 case LY_STMT_STATUS:
3488 /* single item */
3489 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3490 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3491 rc = LY_EVALID;
3492 goto cleanup;
3493 }
3494
3495 /* parse */
3496 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3497 break;
3498
Michal Vasko59892dd2022-05-13 11:02:30 +02003499 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003500 LOGINT(PARSER_CTX(pctx));
3501 rc = LY_EINT;
3502 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003503 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003504
3505cleanup:
3506 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003507}