blob: 765ef5a0eb1b90239bb33916d8bf21f3dce9a09e [file] [log] [blame]
Radek Krejci335332a2019-09-05 13:03:35 +02001/**
Michal Vasko59892dd2022-05-13 11:02:30 +02002 * @file parser_common.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief libyang common parser functions.
Radek Krejci335332a2019-09-05 13:03:35 +02005 *
Michal Vasko59892dd2022-05-13 11:02:30 +02006 * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
Radek Krejci335332a2019-09-05 13:03:35 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Michal Vasko59892dd2022-05-13 11:02:30 +020015#define _GNU_SOURCE
16#define _POSIX_C_SOURCE 200809L /* strdup, strndup */
17
18#ifdef __APPLE__
19#define _DARWIN_C_SOURCE /* F_GETPATH */
20#endif
21
22#if defined (__NetBSD__) || defined (__OpenBSD__)
23/* realpath */
24#define _XOPEN_SOURCE 1
25#define _XOPEN_SOURCE_EXTENDED 1
26#endif
27
28#include "parser_internal.h"
29
Radek Krejci335332a2019-09-05 13:03:35 +020030#include <assert.h>
31#include <ctype.h>
32#include <errno.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020033#include <fcntl.h>
34#include <limits.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020035#include <stdint.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020036#include <stdio.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020037#include <stdlib.h>
38#include <string.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020039#include <unistd.h>
Radek Krejci335332a2019-09-05 13:03:35 +020040
Radek Krejci535ea9f2020-05-29 16:01:05 +020041#include "common.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020042#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020043#include "dict.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020044#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010045#include "log.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020046#include "parser_data.h"
Michal Vasko69730152020-10-09 16:30:07 +020047#include "path.h"
Michal Vaskob4750962022-10-06 15:33:35 +020048#include "plugins_exts/metadata.h"
Michal Vasko193dacd2022-10-13 08:43:05 +020049#include "schema_features.h"
Radek Krejci77114102021-03-10 15:21:57 +010050#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020051#include "tree.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020052#include "tree_data.h"
53#include "tree_data_internal.h"
Radek Krejci335332a2019-09-05 13:03:35 +020054#include "tree_schema.h"
55#include "tree_schema_internal.h"
56
Michal Vasko59892dd2022-05-13 11:02:30 +020057void
58lyd_ctx_free(struct lyd_ctx *lydctx)
59{
60 ly_set_erase(&lydctx->node_types, NULL);
61 ly_set_erase(&lydctx->meta_types, NULL);
62 ly_set_erase(&lydctx->node_when, NULL);
Michal Vasko135719f2022-08-25 12:18:17 +020063 ly_set_erase(&lydctx->ext_node, free);
Michal Vasko59892dd2022-05-13 11:02:30 +020064 ly_set_erase(&lydctx->ext_val, free);
65}
66
67LY_ERR
68lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op)
69{
70 const struct lyd_node *iter;
71
72 *op = NULL;
73
74 if (!parent) {
75 /* no parent, nothing to look for */
76 return LY_SUCCESS;
77 }
78
79 /* we need to find the operation node if it already exists */
80 for (iter = parent; iter; iter = lyd_parent(iter)) {
81 if (iter->schema && (iter->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
82 break;
83 }
84 }
85
86 if (!iter) {
87 /* no operation found */
88 return LY_SUCCESS;
89 }
90
Michal Vaskoe3ed7dc2022-11-30 11:39:44 +010091 if (!(int_opts & LYD_INTOPT_ANY)) {
92 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
93 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
94 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
95 return LY_EINVAL;
96 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
97 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
98 iter->schema->name);
99 return LY_EINVAL;
100 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
101 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
102 iter->schema->name);
103 return LY_EINVAL;
104 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
105 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
106 iter->schema->name);
107 return LY_EINVAL;
108 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200109 }
110
111 *op = (struct lyd_node *)iter;
112 return LY_SUCCESS;
113}
114
115LY_ERR
116lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
117{
118 LY_ERR rc = LY_SUCCESS;
119
120 LOG_LOCSET(snode, NULL, NULL, NULL);
121
122 if (lydctx->int_opts & LYD_INTOPT_ANY) {
123 /* nothing to check, everything is allowed */
124 goto cleanup;
125 }
126
127 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
128 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
129 rc = LY_EVALID;
130 goto cleanup;
131 }
132
133 if (snode->nodetype == LYS_RPC) {
134 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
135 if (lydctx->op_node) {
136 goto error_node_dup;
137 }
138 } else {
139 goto error_node_inval;
140 }
141 } else if (snode->nodetype == LYS_ACTION) {
142 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
143 if (lydctx->op_node) {
144 goto error_node_dup;
145 }
146 } else {
147 goto error_node_inval;
148 }
149 } else if (snode->nodetype == LYS_NOTIF) {
150 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
151 if (lydctx->op_node) {
152 goto error_node_dup;
153 }
154 } else {
155 goto error_node_inval;
156 }
157 }
158
159 /* success */
160 goto cleanup;
161
162error_node_dup:
163 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
164 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
165 lydctx->op_node->schema->name);
166 rc = LY_EVALID;
167 goto cleanup;
168
169error_node_inval:
170 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
171 snode->name);
172 rc = LY_EVALID;
173
174cleanup:
175 LOG_LOCBACK(1, 0, 0, 0);
176 return rc;
177}
178
179LY_ERR
180lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
181 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
182{
183 ly_bool incomplete;
184
185 LY_CHECK_RET(lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node));
186
187 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
188 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
189 }
190 return LY_SUCCESS;
191}
192
193LY_ERR
194lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
195 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
196 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
197{
198 ly_bool incomplete;
199 struct lyd_meta *first = NULL;
200
201 if (meta && *meta) {
202 /* remember the first metadata */
203 first = *meta;
204 }
205
206 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
207 hints, ctx_node, 0, &incomplete));
208
209 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
210 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
211 }
212
213 if (first) {
214 /* always return the first metadata */
215 *meta = first;
216 }
217
218 return LY_SUCCESS;
219}
220
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200221LY_ERR
222lyd_parse_check_keys(struct lyd_node *node)
223{
224 const struct lysc_node *skey = NULL;
225 const struct lyd_node *key;
226
227 assert(node->schema->nodetype == LYS_LIST);
228
229 key = lyd_child(node);
230 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
231 if (!key || (key->schema != skey)) {
232 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
233 return LY_EVALID;
234 }
235
236 key = key->next;
237 }
238
239 return LY_SUCCESS;
240}
241
242LY_ERR
243lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
244 struct lysc_ext_instance *ext)
245{
246 struct lyd_meta *meta2, *prev_meta = NULL;
247 struct lyd_ctx_ext_val *ext_val;
248
Michal Vaskobc9f76f2022-12-01 10:31:38 +0100249 if (lydctx->parse_opts & LYD_PARSE_NO_NEW) {
250 node->flags &= ~LYD_NEW;
251 }
252
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200253 if (lysc_has_when(node->schema)) {
Michal Vaskofbb48c22022-11-30 13:28:03 +0100254 if (lydctx->parse_opts & LYD_PARSE_WHEN_TRUE) {
255 /* the condition was true before */
256 node->flags |= LYD_WHEN_TRUE;
257 }
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200258 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
259 /* remember we need to evaluate this node's when */
260 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
261 }
262 }
263
264 LY_LIST_FOR(*meta, meta2) {
265 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
266 meta2->value.boolean) {
267 /* node is default according to the metadata */
268 node->flags |= LYD_DEFAULT;
269
270 /* delete the metadata */
271 if (prev_meta) {
272 prev_meta->next = meta2->next;
Michal Vasko4754d4a2022-12-01 10:11:21 +0100273 } else if (meta != &node->meta) {
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200274 *meta = (*meta)->next;
275 }
276 lyd_free_meta_single(meta2);
Michal Vasko4754d4a2022-12-01 10:11:21 +0100277
278 /* update dflt flag for all parent NP containers */
279 lyd_cont_set_dflt(lyd_parent(node));
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200280 break;
281 }
282
283 prev_meta = meta2;
284 }
285
286 if (ext) {
287 /* parsed for an extension */
288 node->flags |= LYD_EXT;
289
290 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
291 /* rememeber for validation */
292 ext_val = malloc(sizeof *ext_val);
293 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
294 ext_val->ext = ext;
295 ext_val->sibling = node;
296 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
297 }
298 }
299
300 return LY_SUCCESS;
301}
302
Michal Vasko193dacd2022-10-13 08:43:05 +0200303void
304lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
305{
306 char path[PATH_MAX];
307
308#ifndef __APPLE__
309 char proc_path[32];
310 int len;
311#endif
312
313 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
314 if (*filepath) {
315 /* filepath already set */
316 return;
317 }
318
319 switch (in->type) {
320 case LY_IN_FILEPATH:
321 if (realpath(in->method.fpath.filepath, path) != NULL) {
322 lydict_insert(ctx, path, 0, filepath);
323 } else {
324 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
325 }
326
327 break;
328 case LY_IN_FD:
329#ifdef __APPLE__
330 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
331 lydict_insert(ctx, path, 0, filepath);
332 }
333#elif defined _WIN32
334 HANDLE h = _get_osfhandle(in->method.fd);
335 FILE_NAME_INFO info;
336 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
337 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
338 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
339 lydict_insert(ctx, buf, len, filepath);
340 }
341#else
342 /* get URI if there is /proc */
343 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
344 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
345 lydict_insert(ctx, path, len, filepath);
346 }
347#endif
348 break;
349 case LY_IN_MEMORY:
350 case LY_IN_FILE:
351 /* nothing to do */
352 break;
353 default:
354 LOGINT(ctx);
355 break;
356 }
357}
358
Michal Vaskod0625d72022-10-06 15:02:50 +0200359static LY_ERR lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100360 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200361static LY_ERR lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100362 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200363static LY_ERR lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100364 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200365static LY_ERR lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100366 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200367static LY_ERR lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100368 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200369static LY_ERR lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100370 struct lysp_node **siblings);
371
Radek Krejci335332a2019-09-05 13:03:35 +0200372static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200373lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200374{
Radek Krejci857189e2020-09-01 13:26:36 +0200375 uint8_t prefix = 0;
376 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200377 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200378 size_t utf8_char_len;
379
380 while (*val) {
381 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200382 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200383
384 switch (val_type) {
385 case Y_IDENTIF_ARG:
386 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
387 break;
388 case Y_PREF_IDENTIF_ARG:
389 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
390 break;
391 case Y_STR_ARG:
392 case Y_MAYBE_STR_ARG:
393 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
394 break;
395 }
396 first = 0;
397 }
398
399 return LY_SUCCESS;
400}
401
402/**
403 * @brief Parse extension instance.
404 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100405 * @param[in] ctx parser context.
406 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100407 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200408 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
409 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200410 * @return LY_ERR values.
411 */
412static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200413lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200414 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200415{
416 struct lysp_ext_instance *e;
417
Michal Vaskob36053d2020-03-26 15:49:30 +0100418 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200419
420 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200421 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100422 e->parent_stmt = insubstmt;
423 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200424 e->parsed = NULL;
Radek Krejci335332a2019-09-05 13:03:35 +0200425 /* TODO (duplicate) e->child = stmt->child; */
426
427 /* get optional argument */
428 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200429 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200430 }
431
432 return LY_SUCCESS;
433}
434
435/**
436 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
437 * description, etc...
438 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100439 * @param[in] ctx parser context.
440 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200441 * @param[in] substmt_index Index of this substatement.
442 * @param[in,out] value Place to store the parsed value.
443 * @param[in] arg Type of the YANG keyword argument (of the value).
444 * @param[in,out] exts Extension instances to add to.
445 *
446 * @return LY_ERR values.
447 */
448static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200449lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
450 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200451{
Radek Krejci335332a2019-09-05 13:03:35 +0200452 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200453 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200454 return LY_EVALID;
455 }
456
457 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200458 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200459
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100460 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
461 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200462 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100463 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200464 break;
465 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200466 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200467 return LY_EVALID;
468 }
469 }
470 return LY_SUCCESS;
471}
472
473/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200474 * @brief Parse a qname that can have more instances such as if-feature.
475 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100476 * @param[in] ctx parser context.
477 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200478 * @param[in,out] qnames Parsed qnames to add to.
479 * @param[in] arg Type of the expected argument.
480 * @param[in,out] exts Extension instances to add to.
481 *
482 * @return LY_ERR values.
483 */
484static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200485lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
486 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200487{
488 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200489
490 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
491
492 /* allocate new pointer */
493 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
494 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100495 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200496
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100497 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
498 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200499 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100500 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200501 break;
502 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200503 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200504 return LY_EVALID;
505 }
506 }
507 return LY_SUCCESS;
508}
509
510/**
Radek Krejci335332a2019-09-05 13:03:35 +0200511 * @brief Parse a generic text field that can have more instances such as base.
512 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100513 * @param[in] ctx parser context.
514 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200515 * @param[in,out] texts Parsed values to add to.
516 * @param[in] arg Type of the expected argument.
517 * @param[in,out] exts Extension instances to add to.
518 *
519 * @return LY_ERR values.
520 */
521static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200522lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
523 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200524{
525 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200526
527 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
528
529 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100530 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200531 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200532
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100533 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
534 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200535 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100536 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200537 break;
538 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200539 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200540 return LY_EVALID;
541 }
542 }
543 return LY_SUCCESS;
544}
545
546/**
547 * @brief Parse the status statement.
548 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100549 * @param[in] ctx parser context.
550 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200551 * @param[in,out] flags Flags to add to.
552 * @param[in,out] exts Extension instances to add to.
553 *
554 * @return LY_ERR values.
555 */
556static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200557lysp_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 +0200558{
559 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200560
561 if (*flags & LYS_STATUS_MASK) {
562 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
563 return LY_EVALID;
564 }
565
566 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
567 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100568 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200569 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100570 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200571 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100572 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200573 *flags |= LYS_STATUS_OBSLT;
574 } else {
575 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
576 return LY_EVALID;
577 }
578
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100579 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
580 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200581 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100582 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200583 break;
584 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200585 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200586 return LY_EVALID;
587 }
588 }
589 return LY_SUCCESS;
590}
591
592/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100593 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200594 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100595 * @param[in] ctx parser context.
596 * @param[in] stmt Source statement data from the parsed extension instance.
597 * @param[in,out] when_p When pointer to parse to.
598 *
599 * @return LY_ERR values.
600 */
601static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200602lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100603{
604 LY_ERR ret = LY_SUCCESS;
605 struct lysp_when *when;
606
607 if (*when_p) {
608 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
609 return LY_EVALID;
610 }
611
612 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
613
614 when = calloc(1, sizeof *when);
615 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
616 *when_p = when;
617
618 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
619
620 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
621 switch (child->kw) {
622 case LY_STMT_DESCRIPTION:
623 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
624 break;
625 case LY_STMT_REFERENCE:
626 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
627 break;
628 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100629 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100630 break;
631 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200632 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100633 return LY_EVALID;
634 }
635 }
636 return ret;
637}
638
639/**
640 * @brief Parse the config statement.
641 *
642 * @param[in] ctx parser context.
643 * @param[in] stmt Source statement data from the parsed extension instance.
644 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200645 * @param[in,out] exts Extension instances to add to.
646 *
647 * @return LY_ERR values.
648 */
649static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200650lysp_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 +0200651{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100652 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200653
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100654 if (*flags & LYS_CONFIG_MASK) {
655 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
656 return LY_EVALID;
657 }
658
659 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
660 arg_len = strlen(stmt->arg);
661 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
662 *flags |= LYS_CONFIG_W;
663 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
664 *flags |= LYS_CONFIG_R;
665 } else {
666 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
667 return LY_EVALID;
668 }
669
670 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
671 switch (child->kw) {
672 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100673 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100674 break;
675 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200676 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100677 return LY_EVALID;
678 }
679 }
680
681 return LY_SUCCESS;
682}
683
684/**
685 * @brief Parse the mandatory statement.
686 *
687 * @param[in] ctx parser context.
688 * @param[in] stmt Source statement data from the parsed extension instance.
689 * @param[in,out] flags Flags to add to.
690 * @param[in,out] exts Extension instances to add to.
691 *
692 * @return LY_ERR values.
693 */
694static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200695lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200696 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100697{
698 size_t arg_len;
699
700 if (*flags & LYS_MAND_MASK) {
701 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
702 return LY_EVALID;
703 }
704
705 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
706 arg_len = strlen(stmt->arg);
707 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
708 *flags |= LYS_MAND_TRUE;
709 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
710 *flags |= LYS_MAND_FALSE;
711 } else {
712 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
713 return LY_EVALID;
714 }
715
716 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
717 switch (child->kw) {
718 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100719 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100720 break;
721 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200722 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100723 return LY_EVALID;
724 }
725 }
726
727 return LY_SUCCESS;
728}
729
730/**
731 * @brief Parse a restriction such as range or length.
732 *
733 * @param[in] ctx parser context.
734 * @param[in] stmt Source statement data from the parsed extension instance.
735 * @param[in,out] exts Extension instances to add to.
736 *
737 * @return LY_ERR values.
738 */
739static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200740lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100741{
Radek Krejci335332a2019-09-05 13:03:35 +0200742 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200743 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100744 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200745
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100746 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
747 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200748 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100749 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200750 break;
751 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100752 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200753 break;
754 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100755 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200756 break;
757 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100758 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200759 break;
760 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100761 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200762 break;
763 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200764 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200765 return LY_EVALID;
766 }
767 }
768 return LY_SUCCESS;
769}
770
771/**
772 * @brief Parse a restriction that can have more instances such as must.
773 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100774 * @param[in] ctx parser context.
775 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200776 * @param[in,out] restrs Restrictions to add to.
777 *
778 * @return LY_ERR values.
779 */
780static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200781lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200782{
783 struct lysp_restr *restr;
784
Michal Vaskob36053d2020-03-26 15:49:30 +0100785 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100786 return lysp_stmt_restr(ctx, stmt, restr);
787}
788
789/**
790 * @brief Parse the anydata or anyxml statement.
791 *
792 * @param[in] ctx parser context.
793 * @param[in] stmt Source statement data from the parsed extension instance.
794 * @param[in,out] siblings Siblings to add to.
795 *
796 * @return LY_ERR values.
797 */
798static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200799lysp_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 +0100800{
801 struct lysp_node_anydata *any;
802
803 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
804
805 /* create new structure and insert into siblings */
806 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
807
808 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
809 any->parent = parent;
810
811 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
812
813 /* parse substatements */
814 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
815 switch (child->kw) {
816 case LY_STMT_CONFIG:
817 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
818 break;
819 case LY_STMT_DESCRIPTION:
820 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
821 break;
822 case LY_STMT_IF_FEATURE:
823 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
824 break;
825 case LY_STMT_MANDATORY:
826 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
827 break;
828 case LY_STMT_MUST:
829 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
830 break;
831 case LY_STMT_REFERENCE:
832 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
833 break;
834 case LY_STMT_STATUS:
835 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
836 break;
837 case LY_STMT_WHEN:
838 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
839 break;
840 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100841 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100842 break;
843 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200844 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
845 (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 +0100846 return LY_EVALID;
847 }
848 }
849
850 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200851}
852
853/**
854 * @brief Parse the value or position statement. Substatement of type enum statement.
855 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100856 * @param[in] ctx parser context.
857 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200858 * @param[in,out] value Value to write to.
859 * @param[in,out] flags Flags to write to.
860 * @param[in,out] exts Extension instances to add to.
861 *
862 * @return LY_ERR values.
863 */
864static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200865lysp_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 +0200866 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200867{
868 size_t arg_len;
869 char *ptr = NULL;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200870 long long int num = 0;
871 unsigned long long int unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200872
873 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200874 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200875 return LY_EVALID;
876 }
877 *flags |= LYS_SET_VALUE;
878
879 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
880
881 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100882 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
883 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200884 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200885 goto error;
886 }
887
888 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100889 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200890 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200891 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200892 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200893 goto error;
894 }
895 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200896 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200897 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200898 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200899 goto error;
900 }
901 }
902 /* we have not parsed the whole argument */
903 if ((size_t)(ptr - stmt->arg) != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200904 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200905 goto error;
906 }
907 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200908 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200909 goto error;
910 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100911 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200912 *value = num;
913 } else {
914 *value = unum;
915 }
916
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100917 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
918 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200919 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100920 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 +0200921 break;
922 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200923 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200924 return LY_EVALID;
925 }
926 }
927 return LY_SUCCESS;
928
929error:
930 return LY_EVALID;
931}
932
933/**
934 * @brief Parse the enum or bit statement. Substatement of type statement.
935 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100936 * @param[in] ctx parser context.
937 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200938 * @param[in,out] enums Enums or bits to add to.
939 *
940 * @return LY_ERR values.
941 */
942static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200943lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +0200944{
945 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200946
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100947 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 +0200948
Michal Vaskob36053d2020-03-26 15:49:30 +0100949 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200950
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100951 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +0200952 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
953 } /* else nothing specific for YANG_BIT */
954
Radek Krejci011e4aa2020-09-04 15:22:31 +0200955 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +0200956 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +0200957
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100958 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
959 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200960 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100961 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200962 break;
963 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +0200964 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100965 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200966 break;
967 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100968 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200969 break;
970 case LY_STMT_STATUS:
971 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
972 break;
973 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +0200974 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
975 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100976 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200977 break;
978 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +0200979 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
980 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100981 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200982 break;
983 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100984 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200985 break;
986 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200987 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200988 return LY_EVALID;
989 }
990 }
Michal Vasko193dacd2022-10-13 08:43:05 +0200991
Radek Krejci335332a2019-09-05 13:03:35 +0200992 return LY_SUCCESS;
993}
994
995/**
996 * @brief Parse the fraction-digits statement. Substatement of type statement.
997 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100998 * @param[in] ctx parser context.
999 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001000 * @param[in,out] fracdig Value to write to.
1001 * @param[in,out] exts Extension instances to add to.
1002 *
1003 * @return LY_ERR values.
1004 */
1005static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001006lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001007 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001008{
1009 char *ptr;
1010 size_t arg_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001011 unsigned long long int num;
Radek Krejci335332a2019-09-05 13:03:35 +02001012
1013 if (*fracdig) {
1014 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1015 return LY_EVALID;
1016 }
1017
1018 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1019 arg_len = strlen(stmt->arg);
1020 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1021 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1022 return LY_EVALID;
1023 }
1024
1025 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001026 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001027 /* we have not parsed the whole argument */
1028 if ((size_t)(ptr - stmt->arg) != arg_len) {
1029 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1030 return LY_EVALID;
1031 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001032 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001033 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1034 return LY_EVALID;
1035 }
1036 *fracdig = num;
1037
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001038 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1039 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001040 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001041 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001042 break;
1043 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001044 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001045 return LY_EVALID;
1046 }
1047 }
1048 return LY_SUCCESS;
1049}
1050
1051/**
1052 * @brief Parse the require-instance statement. Substatement of type statement.
1053 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001054 * @param[in] ctx parser context.
1055 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001056 * @param[in,out] reqinst Value to write to.
1057 * @param[in,out] flags Flags to write to.
1058 * @param[in,out] exts Extension instances to add to.
1059 *
1060 * @return LY_ERR values.
1061 */
1062static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001063lysp_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 +02001064 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001065{
1066 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001067
1068 if (*flags & LYS_SET_REQINST) {
1069 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1070 return LY_EVALID;
1071 }
1072 *flags |= LYS_SET_REQINST;
1073
1074 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1075 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001076 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001077 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001078 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001079 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1080 return LY_EVALID;
1081 }
1082
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001083 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1084 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001085 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001086 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001087 break;
1088 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001089 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001090 return LY_EVALID;
1091 }
1092 }
1093 return LY_SUCCESS;
1094}
1095
1096/**
1097 * @brief Parse the modifier statement. Substatement of type pattern statement.
1098 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001099 * @param[in] ctx parser context.
1100 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001101 * @param[in,out] pat Value to write to.
1102 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001103 * @return LY_ERR values.
1104 */
1105static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001106lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001107 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001108{
1109 size_t arg_len;
1110 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001111
Radek Krejcif13b87b2020-12-01 22:02:17 +01001112 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001113 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1114 return LY_EVALID;
1115 }
1116
1117 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1118 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001119 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001120 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1121 return LY_EVALID;
1122 }
1123
1124 /* replace the value in the dictionary */
1125 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001126 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001127 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001128 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001129
Radek Krejcif13b87b2020-12-01 22:02:17 +01001130 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1131 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001132 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001133
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001134 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1135 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001136 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001137 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001138 break;
1139 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001140 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001141 return LY_EVALID;
1142 }
1143 }
1144 return LY_SUCCESS;
1145}
1146
1147/**
1148 * @brief Parse the pattern statement. Substatement of type statement.
1149 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001150 * @param[in] ctx parser context.
1151 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001152 * @param[in,out] patterns Restrictions to add to.
1153 *
1154 * @return LY_ERR values.
1155 */
1156static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001157lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001158{
1159 char *buf;
1160 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001161 struct lysp_restr *restr;
1162
1163 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001164 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001165 arg_len = strlen(stmt->arg);
1166
1167 /* add special meaning first byte */
1168 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001169 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001170 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001171 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001172 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001173 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001174 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001175
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001176 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1177 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001178 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001179 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001180 break;
1181 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001182 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001183 break;
1184 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001185 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001186 break;
1187 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001188 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001189 break;
1190 case LY_STMT_MODIFIER:
1191 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001192 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001193 break;
1194 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001195 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001196 break;
1197 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001198 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001199 return LY_EVALID;
1200 }
1201 }
1202 return LY_SUCCESS;
1203}
1204
1205/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001206 * @brief Parse the deviate statement. Substatement of deviation statement.
1207 *
1208 * @param[in] ctx parser context.
1209 * @param[in] stmt Source statement data from the parsed extension instance.
1210 * @param[in,out] devs Array of deviates to add to.
1211 * @param[in,out] exts Extension instances to add to.
1212 * @return LY_ERR values.
1213 */
1214static LY_ERR
1215lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1216{
1217 (void)stmt;
1218 (void)devs;
1219 (void)exts;
1220
1221 /* TODO */
1222 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1223 return LY_EINVAL;
1224}
1225
1226/**
1227 * @brief Parse the deviation statement.
1228 *
1229 * @param[in] ctx parser context.
1230 * @param[in] stmt Source statement data from the parsed extension instance.
1231 * @param[in,out] deviations Array of deviations to add to.
1232 * @return LY_ERR values.
1233 */
1234static LY_ERR
1235lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1236{
1237 struct lysp_deviation *dev;
1238
1239 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1240
1241 /* store nodeid */
1242 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1243 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1244
1245 /* parse substatements */
1246 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1247 switch (child->kw) {
1248 case LY_STMT_DESCRIPTION:
1249 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1250 break;
1251 case LY_STMT_DEVIATE:
1252 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1253 break;
1254 case LY_STMT_REFERENCE:
1255 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1256 break;
1257 case LY_STMT_EXTENSION_INSTANCE:
1258 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1259 break;
1260 default:
1261 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1262 return LY_EVALID;
1263 }
1264 }
1265
1266 return LY_SUCCESS;
1267}
1268
1269/**
1270 * @brief Parse the yang-version statement.
1271 *
1272 * @param[in] ctx parser context.
1273 * @param[in] stmt Source statement data from the parsed extension instance.
1274 * @param[out] version Version to write to.
1275 * @param[in,out] exts Extension instances to add to.
1276 * @return LY_ERR values.
1277 */
1278static LY_ERR
1279lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1280{
1281 if (*version) {
1282 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1283 return LY_EVALID;
1284 }
1285
1286 /* store flag */
1287 if (!strcmp(stmt->arg, "1")) {
1288 *version = LYS_VERSION_1_0;
1289 } else if (!strcmp(stmt->arg, "1.1")) {
1290 *version = LYS_VERSION_1_1;
1291 } else {
1292 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yang-version");
1293 return LY_EVALID;
1294 }
1295
1296 /* parse substatements */
1297 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1298 switch (child->kw) {
1299 case LY_STMT_EXTENSION_INSTANCE:
1300 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1301 break;
1302 default:
1303 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1304 return LY_EVALID;
1305 }
1306 }
1307
1308 return LY_SUCCESS;
1309}
1310
1311/**
1312 * @brief Parse the module statement.
1313 *
1314 * @param[in] ctx parser context.
1315 * @param[in] stmt Source statement data from the parsed extension instance.
1316 * @param[in,out] mod Module to fill.
1317 * @return LY_ERR values.
1318 */
1319static LY_ERR
1320lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1321{
1322 (void)stmt;
1323 (void)mod;
1324
1325 /* TODO */
1326 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1327 return LY_EINVAL;
1328}
1329
1330/**
1331 * @brief Parse the submodule statement.
1332 *
1333 * @param[in] ctx parser context.
1334 * @param[in] stmt Source statement data from the parsed extension instance.
1335 * @param[in,out] submod Module to fill.
1336 * @return LY_ERR values.
1337 */
1338static LY_ERR
1339lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1340{
1341 (void)stmt;
1342 (void)submod;
1343
1344 /* TODO */
1345 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1346 return LY_EINVAL;
1347}
1348
1349/**
1350 * @brief Parse the yin-element statement. Substatement of argument statement.
1351 *
1352 * @param[in] ctx parser context.
1353 * @param[in] stmt Source statement data from the parsed extension instance.
1354 * @param[in,out] flags Flags to write to.
1355 * @param[in,out] exts Extension instances to add to.
1356 * @return LY_ERR values.
1357 */
1358static LY_ERR
1359lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1360{
1361 if (*flags & LYS_YINELEM_MASK) {
1362 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1363 return LY_EVALID;
1364 }
1365
1366 /* store flag */
1367 if (!strcmp(stmt->arg, "true")) {
1368 *flags |= LYS_YINELEM_TRUE;
1369 } else if (!strcmp(stmt->arg, "false")) {
1370 *flags |= LYS_YINELEM_FALSE;
1371 } else {
1372 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yin-element");
1373 return LY_EVALID;
1374 }
1375
1376 /* parse substatements */
1377 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1378 switch (child->kw) {
1379 case LY_STMT_EXTENSION_INSTANCE:
1380 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1381 break;
1382 default:
1383 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1384 return LY_EVALID;
1385 }
1386 }
1387
1388 return LY_SUCCESS;
1389}
1390
1391/**
1392 * @brief Parse the argument statement. Substatement of extension statement.
1393 *
1394 * @param[in] ctx parser context.
1395 * @param[in] stmt Source statement data from the parsed extension instance.
1396 * @param[in,out] ex Extension to fill.
1397 * @return LY_ERR values.
1398 */
1399static LY_ERR
1400lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1401{
1402 if (ex->argname) {
1403 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1404 return LY_EVALID;
1405 }
1406
1407 /* store argument name */
1408 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1409 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1410
1411 /* parse substatements */
1412 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1413 switch (child->kw) {
1414 case LY_STMT_YIN_ELEMENT:
1415 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1416 break;
1417 case LY_STMT_EXTENSION_INSTANCE:
1418 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1419 break;
1420 default:
1421 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1422 return LY_EVALID;
1423 }
1424 }
1425
1426 return LY_SUCCESS;
1427}
1428
1429/**
1430 * @brief Parse the extension statement.
1431 *
1432 * @param[in] ctx parser context.
1433 * @param[in] stmt Source statement data from the parsed extension instance.
1434 * @param[in,out] extensions Array of extensions to add to.
1435 * @return LY_ERR values.
1436 */
1437static LY_ERR
1438lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1439{
1440 struct lysp_ext *ex;
1441
1442 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1443
1444 /* store name */
1445 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1446 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1447
1448 /* parse substatements */
1449 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1450 switch (child->kw) {
1451 case LY_STMT_DESCRIPTION:
1452 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1453 break;
1454 case LY_STMT_REFERENCE:
1455 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1456 break;
1457 case LY_STMT_STATUS:
1458 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1459 break;
1460 case LY_STMT_ARGUMENT:
1461 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1462 break;
1463 case LY_STMT_EXTENSION_INSTANCE:
1464 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1465 break;
1466 default:
1467 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1468 return LY_EVALID;
1469 }
1470 }
1471
1472 return LY_SUCCESS;
1473}
1474
1475/**
1476 * @brief Parse the feature statement.
1477 *
1478 * @param[in] ctx parser context.
1479 * @param[in] stmt Source statement data from the parsed extension instance.
1480 * @param[in,out] features Array of features to add to.
1481 * @return LY_ERR values.
1482 */
1483static LY_ERR
1484lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1485{
1486 struct lysp_feature *feat;
1487
1488 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1489
1490 /* store name */
1491 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1492 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1493
1494 /* parse substatements */
1495 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1496 switch (child->kw) {
1497 case LY_STMT_DESCRIPTION:
1498 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1499 break;
1500 case LY_STMT_IF_FEATURE:
1501 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1502 break;
1503 case LY_STMT_REFERENCE:
1504 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1505 break;
1506 case LY_STMT_STATUS:
1507 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1508 break;
1509 case LY_STMT_EXTENSION_INSTANCE:
1510 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1511 break;
1512 default:
1513 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1514 return LY_EVALID;
1515 }
1516 }
1517
1518 return LY_SUCCESS;
1519}
1520
1521/**
1522 * @brief Parse the identity statement.
1523 *
1524 * @param[in] ctx parser context.
1525 * @param[in] stmt Source statement data from the parsed extension instance.
1526 * @param[in,out] identities Array of identities to add to.
1527 * @return LY_ERR values.
1528 */
1529static LY_ERR
1530lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1531{
1532 struct lysp_ident *ident;
1533
1534 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1535
1536 /* store name */
1537 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1538 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1539
1540 /* parse substatements */
1541 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1542 switch (child->kw) {
1543 case LY_STMT_DESCRIPTION:
1544 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1545 break;
1546 case LY_STMT_IF_FEATURE:
1547 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1548 break;
1549 case LY_STMT_REFERENCE:
1550 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1551 break;
1552 case LY_STMT_STATUS:
1553 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1554 break;
1555 case LY_STMT_BASE:
1556 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1557 break;
1558 case LY_STMT_EXTENSION_INSTANCE:
1559 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1560 break;
1561 default:
1562 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1563 return LY_EVALID;
1564 }
1565 }
1566
1567 return LY_SUCCESS;
1568}
1569
1570/**
1571 * @brief Parse the import statement.
1572 *
1573 * @param[in] ctx parser context.
1574 * @param[in] stmt Source statement data from the parsed extension instance.
1575 * @param[in,out] imports Array of imports to add to.
1576 * @return LY_ERR values.
1577 */
1578static LY_ERR
1579lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1580{
1581 struct lysp_import *imp;
1582 const char *str = NULL;
1583
1584 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1585
1586 /* store name */
1587 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1588 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1589
1590 /* parse substatements */
1591 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1592 switch (child->kw) {
1593 case LY_STMT_PREFIX:
1594 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1595 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1596 break;
1597 case LY_STMT_DESCRIPTION:
1598 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1599 break;
1600 case LY_STMT_REFERENCE:
1601 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1602 break;
1603 case LY_STMT_REVISION_DATE:
1604 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1605 strcpy(imp->rev, str);
1606 lydict_remove(PARSER_CTX(ctx), str);
1607 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1608 break;
1609 case LY_STMT_EXTENSION_INSTANCE:
1610 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1611 break;
1612 default:
1613 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1614 return LY_EVALID;
1615 }
1616 }
1617
1618 return LY_SUCCESS;
1619}
1620
1621/**
1622 * @brief Parse the include statement.
1623 *
1624 * @param[in] ctx parser context.
1625 * @param[in] stmt Source statement data from the parsed extension instance.
1626 * @param[in,out] includes Array of identities to add to.
1627 * @return LY_ERR values.
1628 */
1629static LY_ERR
1630lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1631{
1632 struct lysp_include *inc;
1633 const char *str = NULL;
1634
1635 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1636
1637 /* store name */
1638 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1639 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1640
1641 /* parse substatements */
1642 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1643 switch (child->kw) {
1644 case LY_STMT_DESCRIPTION:
1645 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1646 break;
1647 case LY_STMT_REFERENCE:
1648 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1649 break;
1650 case LY_STMT_REVISION_DATE:
1651 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1652 strcpy(inc->rev, str);
1653 lydict_remove(PARSER_CTX(ctx), str);
1654 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1655 break;
1656 case LY_STMT_EXTENSION_INSTANCE:
1657 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1658 break;
1659 default:
1660 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1661 return LY_EVALID;
1662 }
1663 }
1664
1665 return LY_SUCCESS;
1666}
1667
1668/**
1669 * @brief Parse the revision statement.
1670 *
1671 * @param[in] ctx parser context.
1672 * @param[in] stmt Source statement data from the parsed extension instance.
1673 * @param[in,out] includes Array of identities to add to.
1674 * @return LY_ERR values.
1675 */
1676static LY_ERR
1677lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1678{
1679 struct lysp_revision *rev;
1680
1681 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1682
1683 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001684 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001685 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001686
1687 /* parse substatements */
1688 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1689 switch (child->kw) {
1690 case LY_STMT_DESCRIPTION:
1691 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1692 break;
1693 case LY_STMT_REFERENCE:
1694 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1695 break;
1696 case LY_STMT_EXTENSION_INSTANCE:
1697 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1698 break;
1699 default:
1700 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1701 return LY_EVALID;
1702 }
1703 }
1704
1705 return LY_SUCCESS;
1706}
1707
1708/**
Radek Krejci335332a2019-09-05 13:03:35 +02001709 * @brief Parse the type statement.
1710 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001711 * @param[in] ctx parser context.
1712 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001713 * @param[in,out] type Type to wrote to.
1714 *
1715 * @return LY_ERR values.
1716 */
1717static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001718lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001719{
1720 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001721 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001722 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001723
1724 if (type->name) {
1725 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1726 return LY_EVALID;
1727 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001728
1729 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001730 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001731 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001732
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001733 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1734 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001735 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001736 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001737 type->flags |= LYS_SET_BASE;
1738 break;
1739 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001740 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001741 type->flags |= LYS_SET_BIT;
1742 break;
1743 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001744 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001745 type->flags |= LYS_SET_ENUM;
1746 break;
1747 case LY_STMT_FRACTION_DIGITS:
1748 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1749 type->flags |= LYS_SET_FRDIGITS;
1750 break;
1751 case LY_STMT_LENGTH:
1752 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001753 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001754 return LY_EVALID;
1755 }
1756 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001757 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001758
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001759 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001760 type->flags |= LYS_SET_LENGTH;
1761 break;
1762 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001763 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001764 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001765 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001766 lydict_remove(PARSER_CTX(ctx), str_path);
1767 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001768 type->flags |= LYS_SET_PATH;
1769 break;
1770 case LY_STMT_PATTERN:
1771 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1772 type->flags |= LYS_SET_PATTERN;
1773 break;
1774 case LY_STMT_RANGE:
1775 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001776 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001777 return LY_EVALID;
1778 }
1779 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001780 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001781
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001782 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001783 type->flags |= LYS_SET_RANGE;
1784 break;
1785 case LY_STMT_REQUIRE_INSTANCE:
1786 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001787 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001788 break;
1789 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001790 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001791 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1792 type->flags |= LYS_SET_TYPE;
1793 break;
1794 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001795 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001796 break;
1797 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001798 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001799 return LY_EVALID;
1800 }
1801 }
1802 return LY_SUCCESS;
1803}
1804
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001805/**
1806 * @brief Parse the leaf statement.
1807 *
1808 * @param[in] ctx parser context.
1809 * @param[in] stmt Source statement data from the parsed extension instance.
1810 * @param[in] parent Parent node to connect to (not into).
1811 * @param[in,out] siblings Siblings to add to.
1812 *
1813 * @return LY_ERR values.
1814 */
1815static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001816lysp_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 +01001817{
1818 struct lysp_node_leaf *leaf;
1819
1820 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1821
1822 /* create new leaf structure */
1823 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1824 leaf->nodetype = LYS_LEAF;
1825 leaf->parent = parent;
1826
1827 /* get name */
1828 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1829
1830 /* parse substatements */
1831 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1832 switch (child->kw) {
1833 case LY_STMT_CONFIG:
1834 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1835 break;
1836 case LY_STMT_DEFAULT:
1837 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 +01001838 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001839 break;
1840 case LY_STMT_DESCRIPTION:
1841 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1842 break;
1843 case LY_STMT_IF_FEATURE:
1844 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1845 break;
1846 case LY_STMT_MANDATORY:
1847 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1848 break;
1849 case LY_STMT_MUST:
1850 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1851 break;
1852 case LY_STMT_REFERENCE:
1853 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1854 break;
1855 case LY_STMT_STATUS:
1856 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1857 break;
1858 case LY_STMT_TYPE:
1859 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1860 break;
1861 case LY_STMT_UNITS:
1862 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1863 break;
1864 case LY_STMT_WHEN:
1865 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1866 break;
1867 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001868 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001869 break;
1870 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001871 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001872 return LY_EVALID;
1873 }
1874 }
1875
1876 /* mandatory substatements */
1877 if (!leaf->type.name) {
1878 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1879 return LY_EVALID;
1880 }
1881
1882 return LY_SUCCESS;
1883}
1884
1885/**
1886 * @brief Parse the max-elements statement.
1887 *
1888 * @param[in] ctx parser context.
1889 * @param[in] stmt Source statement data from the parsed extension instance.
1890 * @param[in,out] max Value to write to.
1891 * @param[in,out] flags Flags to write to.
1892 * @param[in,out] exts Extension instances to add to.
1893 *
1894 * @return LY_ERR values.
1895 */
1896static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001897lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
1898 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001899{
1900 size_t arg_len;
1901 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001902 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001903
1904 if (*flags & LYS_SET_MAX) {
1905 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1906 return LY_EVALID;
1907 }
1908 *flags |= LYS_SET_MAX;
1909
1910 /* get value */
1911 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1912 arg_len = strlen(stmt->arg);
1913
1914 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1915 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1916 return LY_EVALID;
1917 }
1918
1919 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1920 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001921 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001922 /* we have not parsed the whole argument */
1923 if ((size_t)(ptr - stmt->arg) != arg_len) {
1924 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1925 return LY_EVALID;
1926 }
1927 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1928 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1929 return LY_EVALID;
1930 }
1931
1932 *max = num;
1933 } else {
1934 /* unbounded */
1935 *max = 0;
1936 }
1937
1938 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1939 switch (child->kw) {
1940 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001941 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001942 break;
1943 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001944 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001945 return LY_EVALID;
1946 }
1947 }
1948
1949 return LY_SUCCESS;
1950}
1951
1952/**
1953 * @brief Parse the min-elements statement.
1954 *
1955 * @param[in] ctx parser context.
1956 * @param[in] stmt Source statement data from the parsed extension instance.
1957 * @param[in,out] min Value to write to.
1958 * @param[in,out] flags Flags to write to.
1959 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001960 * @return LY_ERR values.
1961 */
1962static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001963lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
1964 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001965{
1966 size_t arg_len;
1967 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001968 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001969
1970 if (*flags & LYS_SET_MIN) {
1971 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
1972 return LY_EVALID;
1973 }
1974 *flags |= LYS_SET_MIN;
1975
1976 /* get value */
1977 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1978 arg_len = strlen(stmt->arg);
1979
1980 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
1981 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1982 return LY_EVALID;
1983 }
1984
1985 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001986 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001987 /* we have not parsed the whole argument */
1988 if ((size_t)(ptr - stmt->arg) != arg_len) {
1989 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1990 return LY_EVALID;
1991 }
1992 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1993 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
1994 return LY_EVALID;
1995 }
1996 *min = num;
1997
1998 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1999 switch (child->kw) {
2000 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002001 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002002 break;
2003 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002004 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002005 return LY_EVALID;
2006 }
2007 }
2008
2009 return LY_SUCCESS;
2010}
2011
2012/**
2013 * @brief Parse the ordered-by statement.
2014 *
2015 * @param[in] ctx parser context.
2016 * @param[in] stmt Source statement data from the parsed extension instance.
2017 * @param[in,out] flags Flags to write to.
2018 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002019 * @return LY_ERR values.
2020 */
2021static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002022lysp_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 +01002023{
2024 size_t arg_len;
2025
2026 if (*flags & LYS_ORDBY_MASK) {
2027 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2028 return LY_EVALID;
2029 }
2030
2031 /* get value */
2032 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2033 arg_len = strlen(stmt->arg);
2034 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2035 *flags |= LYS_MAND_TRUE;
2036 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2037 *flags |= LYS_MAND_FALSE;
2038 } else {
2039 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2040 return LY_EVALID;
2041 }
2042
2043 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2044 switch (child->kw) {
2045 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002046 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002047 break;
2048 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002049 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002050 return LY_EVALID;
2051 }
2052 }
2053
2054 return LY_SUCCESS;
2055}
2056
2057/**
2058 * @brief Parse the leaf-list statement.
2059 *
2060 * @param[in] ctx parser context.
2061 * @param[in] stmt Source statement data from the parsed extension instance.
2062 * @param[in] parent Parent node to connect to (not into).
2063 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002064 * @return LY_ERR values.
2065 */
2066static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002067lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002068 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002069{
2070 struct lysp_node_leaflist *llist;
2071
2072 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2073
2074 /* create new leaf-list structure */
2075 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2076 llist->nodetype = LYS_LEAFLIST;
2077 llist->parent = parent;
2078
2079 /* get name */
2080 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2081
2082 /* parse substatements */
2083 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2084 switch (child->kw) {
2085 case LY_STMT_CONFIG:
2086 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2087 break;
2088 case LY_STMT_DEFAULT:
2089 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2090 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2091 break;
2092 case LY_STMT_DESCRIPTION:
2093 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2094 break;
2095 case LY_STMT_IF_FEATURE:
2096 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2097 break;
2098 case LY_STMT_MAX_ELEMENTS:
2099 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2100 break;
2101 case LY_STMT_MIN_ELEMENTS:
2102 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2103 break;
2104 case LY_STMT_MUST:
2105 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2106 break;
2107 case LY_STMT_ORDERED_BY:
2108 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2109 break;
2110 case LY_STMT_REFERENCE:
2111 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2112 break;
2113 case LY_STMT_STATUS:
2114 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2115 break;
2116 case LY_STMT_TYPE:
2117 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2118 break;
2119 case LY_STMT_UNITS:
2120 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2121 break;
2122 case LY_STMT_WHEN:
2123 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2124 break;
2125 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002126 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002127 break;
2128 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002129 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002130 return LY_EVALID;
2131 }
2132 }
2133
2134 /* mandatory substatements */
2135 if (!llist->type.name) {
2136 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2137 return LY_EVALID;
2138 }
2139
2140 return LY_SUCCESS;
2141}
2142
2143/**
2144 * @brief Parse the refine statement.
2145 *
2146 * @param[in] ctx parser context.
2147 * @param[in] stmt Source statement data from the parsed extension instance.
2148 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002149 * @return LY_ERR values.
2150 */
2151static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002152lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002153{
2154 struct lysp_refine *rf;
2155
2156 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2157
2158 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2159
2160 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2161
2162 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2163 switch (child->kw) {
2164 case LY_STMT_CONFIG:
2165 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2166 break;
2167 case LY_STMT_DEFAULT:
2168 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2169 break;
2170 case LY_STMT_DESCRIPTION:
2171 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2172 break;
2173 case LY_STMT_IF_FEATURE:
2174 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2175 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2176 break;
2177 case LY_STMT_MAX_ELEMENTS:
2178 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2179 break;
2180 case LY_STMT_MIN_ELEMENTS:
2181 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2182 break;
2183 case LY_STMT_MUST:
2184 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2185 break;
2186 case LY_STMT_MANDATORY:
2187 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2188 break;
2189 case LY_STMT_REFERENCE:
2190 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2191 break;
2192 case LY_STMT_PRESENCE:
2193 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2194 break;
2195 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002196 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002197 break;
2198 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002199 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002200 return LY_EVALID;
2201 }
2202 }
2203
2204 return LY_SUCCESS;
2205}
2206
2207/**
2208 * @brief Parse the typedef statement.
2209 *
2210 * @param[in] ctx parser context.
2211 * @param[in] stmt Source statement data from the parsed extension instance.
2212 * @param[in] parent Parent node to connect to (not into).
2213 * @param[in,out] typedefs Typedefs to add to.
2214 *
2215 * @return LY_ERR values.
2216 */
2217static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002218lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002219 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002220{
2221 struct lysp_tpdf *tpdf;
2222
2223 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2224
2225 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2226
2227 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2228
2229 /* parse substatements */
2230 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2231 switch (child->kw) {
2232 case LY_STMT_DEFAULT:
2233 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 +01002234 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002235 break;
2236 case LY_STMT_DESCRIPTION:
2237 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2238 break;
2239 case LY_STMT_REFERENCE:
2240 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2241 break;
2242 case LY_STMT_STATUS:
2243 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2244 break;
2245 case LY_STMT_TYPE:
2246 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2247 break;
2248 case LY_STMT_UNITS:
2249 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2250 break;
2251 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002252 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002253 break;
2254 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002255 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002256 return LY_EVALID;
2257 }
2258 }
2259
2260 /* mandatory substatements */
2261 if (!tpdf->type.name) {
2262 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2263 return LY_EVALID;
2264 }
2265
2266 /* store data for collision check */
2267 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2268 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2269 }
2270
2271 return LY_SUCCESS;
2272}
2273
2274/**
2275 * @brief Parse the input or output statement.
2276 *
2277 * @param[in] ctx parser context.
2278 * @param[in] stmt Source statement data from the parsed extension instance.
2279 * @param[in] parent Parent node to connect to (not into).
2280 * @param[in,out] inout_p Input/output pointer to write to.
2281 *
2282 * @return LY_ERR values.
2283 */
2284static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002285lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002286 struct lysp_node_action_inout *inout_p)
2287{
2288 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002289 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002290 return LY_EVALID;
2291 }
2292
2293 /* initiate structure */
2294 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2295 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2296 inout_p->parent = parent;
2297
2298 /* parse substatements */
2299 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2300 switch (child->kw) {
2301 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002302 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002303 /* fall through */
2304 case LY_STMT_ANYXML:
2305 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2306 break;
2307 case LY_STMT_CHOICE:
2308 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2309 break;
2310 case LY_STMT_CONTAINER:
2311 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2312 break;
2313 case LY_STMT_LEAF:
2314 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2315 break;
2316 case LY_STMT_LEAF_LIST:
2317 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2318 break;
2319 case LY_STMT_LIST:
2320 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2321 break;
2322 case LY_STMT_USES:
2323 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2324 break;
2325 case LY_STMT_TYPEDEF:
2326 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2327 break;
2328 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002329 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002330 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2331 break;
2332 case LY_STMT_GROUPING:
2333 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2334 break;
2335 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002336 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002337 break;
2338 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002339 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002340 return LY_EVALID;
2341 }
2342 }
2343
2344 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002345 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002346 return LY_EVALID;
2347 }
2348
2349 return LY_SUCCESS;
2350}
2351
2352/**
2353 * @brief Parse the action statement.
2354 *
2355 * @param[in] ctx parser context.
2356 * @param[in] stmt Source statement data from the parsed extension instance.
2357 * @param[in] parent Parent node to connect to (not into).
2358 * @param[in,out] actions Actions to add to.
2359 *
2360 * @return LY_ERR values.
2361 */
2362static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002363lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002364 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002365{
2366 struct lysp_node_action *act;
2367
2368 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2369
2370 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2371
2372 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2373 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2374 act->parent = parent;
2375
2376 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2377 switch (child->kw) {
2378 case LY_STMT_DESCRIPTION:
2379 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2380 break;
2381 case LY_STMT_IF_FEATURE:
2382 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2383 break;
2384 case LY_STMT_REFERENCE:
2385 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2386 break;
2387 case LY_STMT_STATUS:
2388 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2389 break;
2390
2391 case LY_STMT_INPUT:
2392 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2393 break;
2394 case LY_STMT_OUTPUT:
2395 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2396 break;
2397
2398 case LY_STMT_TYPEDEF:
2399 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2400 break;
2401 case LY_STMT_GROUPING:
2402 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2403 break;
2404 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002405 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 +01002406 break;
2407 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002408 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002409 return LY_EVALID;
2410 }
2411 }
2412
2413 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2414 if (!act->input.nodetype) {
2415 act->input.nodetype = LYS_INPUT;
2416 act->input.parent = &act->node;
2417 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2418 }
2419 if (!act->output.nodetype) {
2420 act->output.nodetype = LYS_OUTPUT;
2421 act->output.parent = &act->node;
2422 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2423 }
2424
2425 return LY_SUCCESS;
2426}
2427
2428/**
2429 * @brief Parse the notification statement.
2430 *
2431 * @param[in] ctx parser context.
2432 * @param[in] stmt Source statement data from the parsed extension instance.
2433 * @param[in] parent Parent node to connect to (not into).
2434 * @param[in,out] notifs Notifications to add to.
2435 *
2436 * @return LY_ERR values.
2437 */
2438static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002439lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002440 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002441{
2442 struct lysp_node_notif *notif;
2443
2444 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2445
2446 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2447
2448 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2449 notif->nodetype = LYS_NOTIF;
2450 notif->parent = parent;
2451
2452 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2453 switch (child->kw) {
2454 case LY_STMT_DESCRIPTION:
2455 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2456 break;
2457 case LY_STMT_IF_FEATURE:
2458 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2459 break;
2460 case LY_STMT_REFERENCE:
2461 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2462 break;
2463 case LY_STMT_STATUS:
2464 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2465 break;
2466
2467 case LY_STMT_ANYDATA:
2468 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2469 /* fall through */
2470 case LY_STMT_ANYXML:
2471 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2472 break;
2473 case LY_STMT_CHOICE:
2474 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2475 break;
2476 case LY_STMT_CONTAINER:
2477 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2478 break;
2479 case LY_STMT_LEAF:
2480 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2481 break;
2482 case LY_STMT_LEAF_LIST:
2483 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2484 break;
2485 case LY_STMT_LIST:
2486 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2487 break;
2488 case LY_STMT_USES:
2489 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2490 break;
2491
2492 case LY_STMT_MUST:
2493 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2494 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2495 break;
2496 case LY_STMT_TYPEDEF:
2497 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2498 break;
2499 case LY_STMT_GROUPING:
2500 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2501 break;
2502 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002503 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002504 break;
2505 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002506 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002507 return LY_EVALID;
2508 }
2509 }
2510
2511 return LY_SUCCESS;
2512}
2513
2514/**
2515 * @brief Parse the grouping statement.
2516 *
2517 * @param[in] ctx parser context.
2518 * @param[in] stmt Source statement data from the parsed extension instance.
2519 * @param[in] parent Parent node to connect to (not into).
2520 * @param[in,out] groupings Groupings to add to.
2521 *
2522 * @return LY_ERR values.
2523 */
2524static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002525lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002526 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002527{
2528 struct lysp_node_grp *grp;
2529
2530 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2531
2532 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2533
2534 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2535 grp->nodetype = LYS_GROUPING;
2536 grp->parent = parent;
2537
2538 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2539 switch (child->kw) {
2540 case LY_STMT_DESCRIPTION:
2541 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2542 break;
2543 case LY_STMT_REFERENCE:
2544 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2545 break;
2546 case LY_STMT_STATUS:
2547 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2548 break;
2549
2550 case LY_STMT_ANYDATA:
2551 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2552 /* fall through */
2553 case LY_STMT_ANYXML:
2554 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2555 break;
2556 case LY_STMT_CHOICE:
2557 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2558 break;
2559 case LY_STMT_CONTAINER:
2560 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2561 break;
2562 case LY_STMT_LEAF:
2563 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2564 break;
2565 case LY_STMT_LEAF_LIST:
2566 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2567 break;
2568 case LY_STMT_LIST:
2569 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2570 break;
2571 case LY_STMT_USES:
2572 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2573 break;
2574
2575 case LY_STMT_TYPEDEF:
2576 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2577 break;
2578 case LY_STMT_ACTION:
2579 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2580 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2581 break;
2582 case LY_STMT_GROUPING:
2583 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2584 break;
2585 case LY_STMT_NOTIFICATION:
2586 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2587 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2588 break;
2589 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002590 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002591 break;
2592 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002593 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002594 return LY_EVALID;
2595 }
2596 }
2597
2598 return LY_SUCCESS;
2599}
2600
2601/**
2602 * @brief Parse the augment statement.
2603 *
2604 * @param[in] ctx parser context.
2605 * @param[in] stmt Source statement data from the parsed extension instance.
2606 * @param[in] parent Parent node to connect to (not into).
2607 * @param[in,out] augments Augments to add to.
2608 *
2609 * @return LY_ERR values.
2610 */
2611static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002612lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002613 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002614{
2615 struct lysp_node_augment *aug;
2616
2617 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2618
2619 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2620
2621 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2622 aug->nodetype = LYS_AUGMENT;
2623 aug->parent = parent;
2624
2625 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2626 switch (child->kw) {
2627 case LY_STMT_DESCRIPTION:
2628 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2629 break;
2630 case LY_STMT_IF_FEATURE:
2631 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2632 break;
2633 case LY_STMT_REFERENCE:
2634 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2635 break;
2636 case LY_STMT_STATUS:
2637 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2638 break;
2639 case LY_STMT_WHEN:
2640 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2641 break;
2642
2643 case LY_STMT_ANYDATA:
2644 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2645 /* fall through */
2646 case LY_STMT_ANYXML:
2647 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2648 break;
2649 case LY_STMT_CASE:
2650 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2651 break;
2652 case LY_STMT_CHOICE:
2653 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2654 break;
2655 case LY_STMT_CONTAINER:
2656 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2657 break;
2658 case LY_STMT_LEAF:
2659 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2660 break;
2661 case LY_STMT_LEAF_LIST:
2662 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2663 break;
2664 case LY_STMT_LIST:
2665 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2666 break;
2667 case LY_STMT_USES:
2668 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2669 break;
2670
2671 case LY_STMT_ACTION:
2672 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2673 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2674 break;
2675 case LY_STMT_NOTIFICATION:
2676 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2677 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2678 break;
2679 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002680 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002681 break;
2682 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002683 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002684 return LY_EVALID;
2685 }
2686 }
2687
2688 return LY_SUCCESS;
2689}
2690
2691/**
2692 * @brief Parse the uses statement.
2693 *
2694 * @param[in] ctx parser context.
2695 * @param[in] stmt Source statement data from the parsed extension instance.
2696 * @param[in] parent Parent node to connect to (not into).
2697 * @param[in,out] siblings Siblings to add to.
2698 *
2699 * @return LY_ERR values.
2700 */
2701static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002702lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002703 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002704{
2705 struct lysp_node_uses *uses;
2706
2707 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2708
2709 /* create uses structure */
2710 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2711
2712 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2713 uses->nodetype = LYS_USES;
2714 uses->parent = parent;
2715
2716 /* parse substatements */
2717 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2718 switch (child->kw) {
2719 case LY_STMT_DESCRIPTION:
2720 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2721 break;
2722 case LY_STMT_IF_FEATURE:
2723 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2724 break;
2725 case LY_STMT_REFERENCE:
2726 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2727 break;
2728 case LY_STMT_STATUS:
2729 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2730 break;
2731 case LY_STMT_WHEN:
2732 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2733 break;
2734
2735 case LY_STMT_REFINE:
2736 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2737 break;
2738 case LY_STMT_AUGMENT:
2739 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2740 break;
2741 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002742 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002743 break;
2744 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002745 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002746 return LY_EVALID;
2747 }
2748 }
2749
2750 return LY_SUCCESS;
2751}
2752
2753/**
2754 * @brief Parse the case statement.
2755 *
2756 * @param[in] ctx parser context.
2757 * @param[in] stmt Source statement data from the parsed extension instance.
2758 * @param[in] parent Parent node to connect to (not into).
2759 * @param[in,out] siblings Siblings to add to.
2760 *
2761 * @return LY_ERR values.
2762 */
2763static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002764lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002765 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002766{
2767 struct lysp_node_case *cas;
2768
2769 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2770
2771 /* create new case structure */
2772 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2773
2774 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2775 cas->nodetype = LYS_CASE;
2776 cas->parent = parent;
2777
2778 /* parse substatements */
2779 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2780 switch (child->kw) {
2781 case LY_STMT_DESCRIPTION:
2782 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2783 break;
2784 case LY_STMT_IF_FEATURE:
2785 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2786 break;
2787 case LY_STMT_REFERENCE:
2788 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2789 break;
2790 case LY_STMT_STATUS:
2791 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2792 break;
2793 case LY_STMT_WHEN:
2794 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2795 break;
2796
2797 case LY_STMT_ANYDATA:
2798 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2799 /* fall through */
2800 case LY_STMT_ANYXML:
2801 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2802 break;
2803 case LY_STMT_CHOICE:
2804 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2805 break;
2806 case LY_STMT_CONTAINER:
2807 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2808 break;
2809 case LY_STMT_LEAF:
2810 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2811 break;
2812 case LY_STMT_LEAF_LIST:
2813 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2814 break;
2815 case LY_STMT_LIST:
2816 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2817 break;
2818 case LY_STMT_USES:
2819 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2820 break;
2821 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002822 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002823 break;
2824 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002825 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002826 return LY_EVALID;
2827 }
2828 }
2829 return LY_SUCCESS;
2830}
2831
2832/**
2833 * @brief Parse the choice statement.
2834 *
2835 * @param[in] ctx parser context.
2836 * @param[in] stmt Source statement data from the parsed extension instance.
2837 * @param[in] parent Parent node to connect to (not into).
2838 * @param[in,out] siblings Siblings to add to.
2839 *
2840 * @return LY_ERR values.
2841 */
2842static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002843lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002844 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002845{
2846 struct lysp_node_choice *choice;
2847
2848 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2849
2850 /* create new choice structure */
2851 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2852
2853 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2854 choice->nodetype = LYS_CHOICE;
2855 choice->parent = parent;
2856
2857 /* parse substatements */
2858 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2859 switch (child->kw) {
2860 case LY_STMT_CONFIG:
2861 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2862 break;
2863 case LY_STMT_DESCRIPTION:
2864 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2865 break;
2866 case LY_STMT_IF_FEATURE:
2867 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2868 break;
2869 case LY_STMT_MANDATORY:
2870 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2871 break;
2872 case LY_STMT_REFERENCE:
2873 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2874 break;
2875 case LY_STMT_STATUS:
2876 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2877 break;
2878 case LY_STMT_WHEN:
2879 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2880 break;
2881 case LY_STMT_DEFAULT:
2882 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 +01002883 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002884 break;
2885 case LY_STMT_ANYDATA:
2886 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2887 /* fall through */
2888 case LY_STMT_ANYXML:
2889 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2890 break;
2891 case LY_STMT_CASE:
2892 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2893 break;
2894 case LY_STMT_CHOICE:
2895 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2896 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2897 break;
2898 case LY_STMT_CONTAINER:
2899 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2900 break;
2901 case LY_STMT_LEAF:
2902 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2903 break;
2904 case LY_STMT_LEAF_LIST:
2905 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2906 break;
2907 case LY_STMT_LIST:
2908 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2909 break;
2910 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002911 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002912 break;
2913 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002914 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002915 return LY_EVALID;
2916 }
2917 }
2918 return LY_SUCCESS;
2919}
2920
2921/**
2922 * @brief Parse the container statement.
2923 *
2924 * @param[in] ctx parser context.
2925 * @param[in] stmt Source statement data from the parsed extension instance.
2926 * @param[in] parent Parent node to connect to (not into).
2927 * @param[in,out] siblings Siblings to add to.
2928 *
2929 * @return LY_ERR values.
2930 */
2931static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002932lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002933 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002934{
2935 struct lysp_node_container *cont;
2936
2937 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2938
2939 /* create new container structure */
2940 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2941
2942 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2943 cont->nodetype = LYS_CONTAINER;
2944 cont->parent = parent;
2945
2946 /* parse substatements */
2947 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2948 switch (child->kw) {
2949 case LY_STMT_CONFIG:
2950 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
2951 break;
2952 case LY_STMT_DESCRIPTION:
2953 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
2954 break;
2955 case LY_STMT_IF_FEATURE:
2956 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
2957 break;
2958 case LY_STMT_REFERENCE:
2959 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
2960 break;
2961 case LY_STMT_STATUS:
2962 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
2963 break;
2964 case LY_STMT_WHEN:
2965 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
2966 break;
2967 case LY_STMT_PRESENCE:
2968 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
2969 break;
2970 case LY_STMT_ANYDATA:
2971 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
2972 /* fall through */
2973 case LY_STMT_ANYXML:
2974 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
2975 break;
2976 case LY_STMT_CHOICE:
2977 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
2978 break;
2979 case LY_STMT_CONTAINER:
2980 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
2981 break;
2982 case LY_STMT_LEAF:
2983 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
2984 break;
2985 case LY_STMT_LEAF_LIST:
2986 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
2987 break;
2988 case LY_STMT_LIST:
2989 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
2990 break;
2991 case LY_STMT_USES:
2992 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
2993 break;
2994
2995 case LY_STMT_TYPEDEF:
2996 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
2997 break;
2998 case LY_STMT_MUST:
2999 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
3000 break;
3001 case LY_STMT_ACTION:
3002 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
3003 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
3004 break;
3005 case LY_STMT_GROUPING:
3006 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3007 break;
3008 case LY_STMT_NOTIFICATION:
3009 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3010 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3011 break;
3012 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003013 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003014 break;
3015 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003016 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003017 return LY_EVALID;
3018 }
3019 }
3020
3021 return LY_SUCCESS;
3022}
3023
3024/**
3025 * @brief Parse the list statement.
3026 *
3027 * @param[in] ctx parser context.
3028 * @param[in] stmt Source statement data from the parsed extension instance.
3029 * @param[in] parent Parent node to connect to (not into).
3030 * @param[in,out] siblings Siblings to add to.
3031 *
3032 * @return LY_ERR values.
3033 */
3034static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003035lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003036 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003037{
3038 struct lysp_node_list *list;
3039
3040 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3041
3042 /* create new list structure */
3043 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3044
3045 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3046 list->nodetype = LYS_LIST;
3047 list->parent = parent;
3048
3049 /* parse substatements */
3050 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3051 switch (child->kw) {
3052 case LY_STMT_CONFIG:
3053 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3054 break;
3055 case LY_STMT_DESCRIPTION:
3056 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3057 break;
3058 case LY_STMT_IF_FEATURE:
3059 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3060 break;
3061 case LY_STMT_REFERENCE:
3062 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3063 break;
3064 case LY_STMT_STATUS:
3065 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3066 break;
3067 case LY_STMT_WHEN:
3068 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3069 break;
3070 case LY_STMT_KEY:
3071 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3072 break;
3073 case LY_STMT_MAX_ELEMENTS:
3074 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3075 break;
3076 case LY_STMT_MIN_ELEMENTS:
3077 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3078 break;
3079 case LY_STMT_ORDERED_BY:
3080 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3081 break;
3082 case LY_STMT_UNIQUE:
3083 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3084 break;
3085
3086 case LY_STMT_ANYDATA:
3087 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3088 /* fall through */
3089 case LY_STMT_ANYXML:
3090 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3091 break;
3092 case LY_STMT_CHOICE:
3093 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3094 break;
3095 case LY_STMT_CONTAINER:
3096 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3097 break;
3098 case LY_STMT_LEAF:
3099 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3100 break;
3101 case LY_STMT_LEAF_LIST:
3102 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3103 break;
3104 case LY_STMT_LIST:
3105 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3106 break;
3107 case LY_STMT_USES:
3108 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3109 break;
3110
3111 case LY_STMT_TYPEDEF:
3112 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3113 break;
3114 case LY_STMT_MUST:
3115 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3116 break;
3117 case LY_STMT_ACTION:
3118 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3119 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3120 break;
3121 case LY_STMT_GROUPING:
3122 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3123 break;
3124 case LY_STMT_NOTIFICATION:
3125 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3126 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3127 break;
3128 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003129 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003130 break;
3131 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003132 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003133 return LY_EVALID;
3134 }
3135 }
3136
3137 return LY_SUCCESS;
3138}
3139
Michal Vasko193dacd2022-10-13 08:43:05 +02003140/**
3141 * @brief Parse generic statement structure into a specific parsed-schema structure.
3142 *
3143 * @param[in] pctx Parse context of the @p stmt being processed.
3144 * @param[in] stmt Generic statement structure to process.
3145 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3146 * @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.
3147 * @return LY_ERR value.
3148 */
3149static LY_ERR
3150lysp_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 +02003151{
Radek Krejciad5963b2019-09-06 16:03:05 +02003152 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003153 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003154
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003155 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003156 case LY_STMT_NOTIFICATION:
3157 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3158 break;
3159 case LY_STMT_INPUT:
3160 case LY_STMT_OUTPUT: {
3161 struct lysp_node_action_inout *inout;
3162
3163 *result = inout = calloc(1, sizeof *inout);
3164 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3165 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3166 break;
3167 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003168 case LY_STMT_ACTION:
3169 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003170 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003171 break;
3172 case LY_STMT_ANYDATA:
3173 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003174 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003175 break;
3176 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003177 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003178 break;
3179 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003180 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003181 break;
3182 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003183 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003184 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003185 case LY_STMT_CONTAINER:
3186 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003187 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003188 case LY_STMT_GROUPING:
3189 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3190 break;
3191 case LY_STMT_LEAF:
3192 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3193 break;
3194 case LY_STMT_LEAF_LIST:
3195 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3196 break;
3197 case LY_STMT_LIST:
3198 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3199 break;
3200 case LY_STMT_USES:
3201 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3202 break;
3203 case LY_STMT_BASE:
3204 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3205 break;
3206 case LY_STMT_ARGUMENT:
3207 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003208 case LY_STMT_CONTACT:
3209 case LY_STMT_DESCRIPTION:
3210 case LY_STMT_ERROR_APP_TAG:
3211 case LY_STMT_ERROR_MESSAGE:
3212 case LY_STMT_KEY:
3213 case LY_STMT_NAMESPACE:
3214 case LY_STMT_ORGANIZATION:
3215 case LY_STMT_PRESENCE:
3216 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003217 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003218 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003219 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003220 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003221 case LY_STMT_BIT:
3222 case LY_STMT_ENUM:
3223 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3224 break;
3225 case LY_STMT_CONFIG:
3226 assert(*result);
3227 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003228 break;
3229 case LY_STMT_DEFAULT:
3230 case LY_STMT_IF_FEATURE:
3231 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003232 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3233 break;
3234 case LY_STMT_DEVIATE:
3235 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3236 break;
3237 case LY_STMT_DEVIATION:
3238 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3239 break;
3240 case LY_STMT_EXTENSION:
3241 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003242 break;
3243 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003244 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3245 break;
3246 case LY_STMT_FEATURE:
3247 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003248 break;
3249 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003250 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003251 break;
3252 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003253 case LY_STMT_RANGE: {
3254 struct lysp_restr *restr;
3255
3256 *result = restr = calloc(1, sizeof *restr);
3257 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3258
3259 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003260 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003261 }
3262 case LY_STMT_MUST:
3263 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3264 break;
3265 case LY_STMT_IDENTITY:
3266 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3267 break;
3268 case LY_STMT_IMPORT:
3269 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3270 break;
3271 case LY_STMT_INCLUDE:
3272 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003273 break;
3274 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003275 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003276 break;
3277 case LY_STMT_MAX_ELEMENTS:
3278 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003279 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003280 break;
3281 case LY_STMT_MIN_ELEMENTS:
3282 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003283 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003284 break;
3285 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003286 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003287 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003288 case LY_STMT_MODULE: {
3289 struct lysp_module *mod;
3290
3291 *result = mod = calloc(1, sizeof *mod);
3292 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3293 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003294 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003295 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003296 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003297 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003298 break;
3299 case LY_STMT_PATH: {
3300 const char *str_path = NULL;
3301
Michal Vasko193dacd2022-10-13 08:43:05 +02003302 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3303 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003304 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003305 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003306 break;
3307 }
3308 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003309 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003310 break;
3311 case LY_STMT_POSITION:
3312 case LY_STMT_VALUE:
3313 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003314 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003315 break;
3316 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003317 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003318 break;
3319 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003320 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003321 break;
3322 case LY_STMT_REQUIRE_INSTANCE:
3323 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003324 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3325 break;
3326 case LY_STMT_REVISION:
3327 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003328 break;
Michal Vasko69730152020-10-09 16:30:07 +02003329 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003330 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003331 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003332 case LY_STMT_SUBMODULE: {
3333 struct lysp_submodule *submod;
3334
3335 *result = submod = calloc(1, sizeof *submod);
3336 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3337 ret = lysp_stmt_submodule(pctx, stmt, submod);
3338 break;
3339 }
Radek Krejci335332a2019-09-05 13:03:35 +02003340 case LY_STMT_TYPE: {
3341 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003342
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003343 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003344 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3345 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003346 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003347 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003348 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003349 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003350 break;
3351 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003352 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3353 break;
3354 case LY_STMT_YANG_VERSION:
3355 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3356 break;
3357 case LY_STMT_YIN_ELEMENT:
3358 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003359 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003360 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003361 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003362 return LY_EINT;
3363 }
3364
Radek Krejciad5963b2019-09-06 16:03:05 +02003365 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003366}
Michal Vasko59892dd2022-05-13 11:02:30 +02003367
Michal Vasko193dacd2022-10-13 08:43:05 +02003368LY_ERR
3369lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003370{
Michal Vasko193dacd2022-10-13 08:43:05 +02003371 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003372
Michal Vasko193dacd2022-10-13 08:43:05 +02003373 if (!substmt->storage) {
3374 /* nothing to parse, ignored */
3375 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003376 }
3377
Michal Vasko193dacd2022-10-13 08:43:05 +02003378 switch (stmt->kw) {
3379 case LY_STMT_NOTIFICATION:
3380 case LY_STMT_INPUT:
3381 case LY_STMT_OUTPUT:
3382 case LY_STMT_ACTION:
3383 case LY_STMT_RPC:
3384 case LY_STMT_ANYDATA:
3385 case LY_STMT_ANYXML:
3386 case LY_STMT_AUGMENT:
3387 case LY_STMT_CASE:
3388 case LY_STMT_CHOICE:
3389 case LY_STMT_CONTAINER:
3390 case LY_STMT_GROUPING:
3391 case LY_STMT_LEAF:
3392 case LY_STMT_LEAF_LIST:
3393 case LY_STMT_LIST:
3394 case LY_STMT_USES: {
3395 struct lysp_node **pnodes_p, *pnode = NULL;
3396
3397 /* parse the node */
3398 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3399
3400 /* usually is a linked-list of all the parsed schema nodes */
3401 pnodes_p = substmt->storage;
3402 while (*pnodes_p) {
3403 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003404 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003405 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003406
3407 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003408 }
3409 case LY_STMT_BASE:
3410 case LY_STMT_BIT:
3411 case LY_STMT_DEFAULT:
3412 case LY_STMT_DEVIATE:
3413 case LY_STMT_DEVIATION:
3414 case LY_STMT_ENUM:
3415 case LY_STMT_EXTENSION:
3416 case LY_STMT_EXTENSION_INSTANCE:
3417 case LY_STMT_FEATURE:
3418 case LY_STMT_IDENTITY:
3419 case LY_STMT_IF_FEATURE:
3420 case LY_STMT_IMPORT:
3421 case LY_STMT_INCLUDE:
3422 case LY_STMT_MUST:
3423 case LY_STMT_PATTERN:
3424 case LY_STMT_REFINE:
3425 case LY_STMT_REVISION:
3426 case LY_STMT_TYPEDEF:
3427 case LY_STMT_UNIQUE:
3428 /* parse, sized array */
3429 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003430 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003431
3432 case LY_STMT_ARGUMENT:
3433 case LY_STMT_BELONGS_TO:
3434 case LY_STMT_CONTACT:
3435 case LY_STMT_DESCRIPTION:
3436 case LY_STMT_ERROR_APP_TAG:
3437 case LY_STMT_ERROR_MESSAGE:
3438 case LY_STMT_FRACTION_DIGITS:
3439 case LY_STMT_KEY:
3440 case LY_STMT_LENGTH:
3441 case LY_STMT_MANDATORY:
3442 case LY_STMT_MAX_ELEMENTS:
3443 case LY_STMT_MIN_ELEMENTS:
3444 case LY_STMT_MODIFIER:
3445 case LY_STMT_MODULE:
3446 case LY_STMT_NAMESPACE:
3447 case LY_STMT_ORGANIZATION:
3448 case LY_STMT_PATH:
3449 case LY_STMT_POSITION:
3450 case LY_STMT_PREFIX:
3451 case LY_STMT_PRESENCE:
3452 case LY_STMT_RANGE:
3453 case LY_STMT_REFERENCE:
3454 case LY_STMT_REQUIRE_INSTANCE:
3455 case LY_STMT_REVISION_DATE:
3456 case LY_STMT_SUBMODULE:
3457 case LY_STMT_TYPE:
3458 case LY_STMT_UNITS:
3459 case LY_STMT_VALUE:
3460 case LY_STMT_WHEN:
3461 case LY_STMT_YANG_VERSION:
3462 case LY_STMT_YIN_ELEMENT:
3463 /* single item */
3464 if (*(void **)substmt->storage) {
3465 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3466 rc = LY_EVALID;
3467 goto cleanup;
3468 }
3469
3470 /* parse */
3471 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003472 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003473
3474 case LY_STMT_CONFIG:
3475 /* single item */
3476 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3477 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3478 rc = LY_EVALID;
3479 goto cleanup;
3480 }
3481
3482 /* parse */
3483 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3484 break;
3485
3486 case LY_STMT_ORDERED_BY:
3487 /* single item */
3488 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3489 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3490 rc = LY_EVALID;
3491 goto cleanup;
3492 }
3493
3494 /* parse */
3495 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3496 break;
3497
3498 case LY_STMT_STATUS:
3499 /* single item */
3500 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3501 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3502 rc = LY_EVALID;
3503 goto cleanup;
3504 }
3505
3506 /* parse */
3507 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3508 break;
3509
Michal Vasko59892dd2022-05-13 11:02:30 +02003510 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003511 LOGINT(PARSER_CTX(pctx));
3512 rc = LY_EINT;
3513 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003514 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003515
3516cleanup:
3517 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003518}