blob: cf509ca39f66dad1df715188608d4f907febc27e [file] [log] [blame]
Radek Krejci335332a2019-09-05 13:03:35 +02001/**
Michal Vasko59892dd2022-05-13 11:02:30 +02002 * @file parser_common.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief libyang common parser functions.
Radek Krejci335332a2019-09-05 13:03:35 +02005 *
Michal Vasko59892dd2022-05-13 11:02:30 +02006 * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
Radek Krejci335332a2019-09-05 13:03:35 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Michal Vasko59892dd2022-05-13 11:02:30 +020015#define _GNU_SOURCE
16#define _POSIX_C_SOURCE 200809L /* strdup, strndup */
17
18#ifdef __APPLE__
19#define _DARWIN_C_SOURCE /* F_GETPATH */
20#endif
21
22#if defined (__NetBSD__) || defined (__OpenBSD__)
23/* realpath */
24#define _XOPEN_SOURCE 1
25#define _XOPEN_SOURCE_EXTENDED 1
26#endif
27
28#include "parser_internal.h"
29
Radek Krejci335332a2019-09-05 13:03:35 +020030#include <assert.h>
31#include <ctype.h>
32#include <errno.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020033#include <fcntl.h>
34#include <limits.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020035#include <stdint.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020036#include <stdio.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020037#include <stdlib.h>
38#include <string.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020039#include <unistd.h>
Radek Krejci335332a2019-09-05 13:03:35 +020040
Radek Krejci535ea9f2020-05-29 16:01:05 +020041#include "common.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020042#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020043#include "dict.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020044#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010045#include "log.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020046#include "parser_data.h"
Michal Vasko69730152020-10-09 16:30:07 +020047#include "path.h"
Michal Vaskob4750962022-10-06 15:33:35 +020048#include "plugins_exts/metadata.h"
Michal Vasko193dacd2022-10-13 08:43:05 +020049#include "schema_features.h"
Radek Krejci77114102021-03-10 15:21:57 +010050#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020051#include "tree.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020052#include "tree_data.h"
53#include "tree_data_internal.h"
Radek Krejci335332a2019-09-05 13:03:35 +020054#include "tree_schema.h"
55#include "tree_schema_internal.h"
56
Michal Vasko59892dd2022-05-13 11:02:30 +020057void
58lyd_ctx_free(struct lyd_ctx *lydctx)
59{
60 ly_set_erase(&lydctx->node_types, NULL);
61 ly_set_erase(&lydctx->meta_types, NULL);
62 ly_set_erase(&lydctx->node_when, NULL);
Michal Vasko135719f2022-08-25 12:18:17 +020063 ly_set_erase(&lydctx->ext_node, free);
Michal Vasko59892dd2022-05-13 11:02:30 +020064 ly_set_erase(&lydctx->ext_val, free);
65}
66
67LY_ERR
68lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op)
69{
70 const struct lyd_node *iter;
71
72 *op = NULL;
73
74 if (!parent) {
75 /* no parent, nothing to look for */
76 return LY_SUCCESS;
77 }
78
79 /* we need to find the operation node if it already exists */
80 for (iter = parent; iter; iter = lyd_parent(iter)) {
81 if (iter->schema && (iter->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
82 break;
83 }
84 }
85
86 if (!iter) {
87 /* no operation found */
88 return LY_SUCCESS;
89 }
90
Michal Vaskoe3ed7dc2022-11-30 11:39:44 +010091 if (!(int_opts & LYD_INTOPT_ANY)) {
92 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
93 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
94 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
95 return LY_EINVAL;
96 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
97 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
98 iter->schema->name);
99 return LY_EINVAL;
100 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
101 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
102 iter->schema->name);
103 return LY_EINVAL;
104 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
105 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
106 iter->schema->name);
107 return LY_EINVAL;
108 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200109 }
110
111 *op = (struct lyd_node *)iter;
112 return LY_SUCCESS;
113}
114
115LY_ERR
116lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
117{
118 LY_ERR rc = LY_SUCCESS;
119
120 LOG_LOCSET(snode, NULL, NULL, NULL);
121
122 if (lydctx->int_opts & LYD_INTOPT_ANY) {
123 /* nothing to check, everything is allowed */
124 goto cleanup;
125 }
126
127 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
128 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
129 rc = LY_EVALID;
130 goto cleanup;
131 }
132
133 if (snode->nodetype == LYS_RPC) {
134 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
135 if (lydctx->op_node) {
136 goto error_node_dup;
137 }
138 } else {
139 goto error_node_inval;
140 }
141 } else if (snode->nodetype == LYS_ACTION) {
142 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
143 if (lydctx->op_node) {
144 goto error_node_dup;
145 }
146 } else {
147 goto error_node_inval;
148 }
149 } else if (snode->nodetype == LYS_NOTIF) {
150 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
151 if (lydctx->op_node) {
152 goto error_node_dup;
153 }
154 } else {
155 goto error_node_inval;
156 }
157 }
158
159 /* success */
160 goto cleanup;
161
162error_node_dup:
163 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
164 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
165 lydctx->op_node->schema->name);
166 rc = LY_EVALID;
167 goto cleanup;
168
169error_node_inval:
170 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
171 snode->name);
172 rc = LY_EVALID;
173
174cleanup:
175 LOG_LOCBACK(1, 0, 0, 0);
176 return rc;
177}
178
179LY_ERR
180lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
181 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
182{
183 ly_bool incomplete;
184
185 LY_CHECK_RET(lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node));
186
187 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
188 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
189 }
190 return LY_SUCCESS;
191}
192
193LY_ERR
194lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
195 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
196 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
197{
198 ly_bool incomplete;
199 struct lyd_meta *first = NULL;
200
201 if (meta && *meta) {
202 /* remember the first metadata */
203 first = *meta;
204 }
205
206 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
207 hints, ctx_node, 0, &incomplete));
208
209 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
210 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
211 }
212
213 if (first) {
214 /* always return the first metadata */
215 *meta = first;
216 }
217
218 return LY_SUCCESS;
219}
220
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200221LY_ERR
222lyd_parse_check_keys(struct lyd_node *node)
223{
224 const struct lysc_node *skey = NULL;
225 const struct lyd_node *key;
226
227 assert(node->schema->nodetype == LYS_LIST);
228
229 key = lyd_child(node);
230 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
231 if (!key || (key->schema != skey)) {
232 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
233 return LY_EVALID;
234 }
235
236 key = key->next;
237 }
238
239 return LY_SUCCESS;
240}
241
242LY_ERR
243lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
244 struct lysc_ext_instance *ext)
245{
246 struct lyd_meta *meta2, *prev_meta = NULL;
247 struct lyd_ctx_ext_val *ext_val;
248
249 if (lysc_has_when(node->schema)) {
Michal Vaskofbb48c22022-11-30 13:28:03 +0100250 if (lydctx->parse_opts & LYD_PARSE_WHEN_TRUE) {
251 /* the condition was true before */
252 node->flags |= LYD_WHEN_TRUE;
253 }
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200254 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
255 /* remember we need to evaluate this node's when */
256 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
257 }
258 }
259
260 LY_LIST_FOR(*meta, meta2) {
261 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
262 meta2->value.boolean) {
263 /* node is default according to the metadata */
264 node->flags |= LYD_DEFAULT;
265
266 /* delete the metadata */
267 if (prev_meta) {
268 prev_meta->next = meta2->next;
Michal Vasko4754d4a2022-12-01 10:11:21 +0100269 } else if (meta != &node->meta) {
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200270 *meta = (*meta)->next;
271 }
272 lyd_free_meta_single(meta2);
Michal Vasko4754d4a2022-12-01 10:11:21 +0100273
274 /* update dflt flag for all parent NP containers */
275 lyd_cont_set_dflt(lyd_parent(node));
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200276 break;
277 }
278
279 prev_meta = meta2;
280 }
281
282 if (ext) {
283 /* parsed for an extension */
284 node->flags |= LYD_EXT;
285
286 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
287 /* rememeber for validation */
288 ext_val = malloc(sizeof *ext_val);
289 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
290 ext_val->ext = ext;
291 ext_val->sibling = node;
292 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
293 }
294 }
295
296 return LY_SUCCESS;
297}
298
Michal Vasko193dacd2022-10-13 08:43:05 +0200299void
300lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
301{
302 char path[PATH_MAX];
303
304#ifndef __APPLE__
305 char proc_path[32];
306 int len;
307#endif
308
309 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
310 if (*filepath) {
311 /* filepath already set */
312 return;
313 }
314
315 switch (in->type) {
316 case LY_IN_FILEPATH:
317 if (realpath(in->method.fpath.filepath, path) != NULL) {
318 lydict_insert(ctx, path, 0, filepath);
319 } else {
320 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
321 }
322
323 break;
324 case LY_IN_FD:
325#ifdef __APPLE__
326 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
327 lydict_insert(ctx, path, 0, filepath);
328 }
329#elif defined _WIN32
330 HANDLE h = _get_osfhandle(in->method.fd);
331 FILE_NAME_INFO info;
332 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
333 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
334 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
335 lydict_insert(ctx, buf, len, filepath);
336 }
337#else
338 /* get URI if there is /proc */
339 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
340 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
341 lydict_insert(ctx, path, len, filepath);
342 }
343#endif
344 break;
345 case LY_IN_MEMORY:
346 case LY_IN_FILE:
347 /* nothing to do */
348 break;
349 default:
350 LOGINT(ctx);
351 break;
352 }
353}
354
Michal Vaskod0625d72022-10-06 15:02:50 +0200355static 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 +0100356 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200357static 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 +0100358 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200359static 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 +0100360 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200361static 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 +0100362 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200363static 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 +0100364 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200365static 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 +0100366 struct lysp_node **siblings);
367
Radek Krejci335332a2019-09-05 13:03:35 +0200368static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200369lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200370{
Radek Krejci857189e2020-09-01 13:26:36 +0200371 uint8_t prefix = 0;
372 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200373 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200374 size_t utf8_char_len;
375
376 while (*val) {
377 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200378 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200379
380 switch (val_type) {
381 case Y_IDENTIF_ARG:
382 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
383 break;
384 case Y_PREF_IDENTIF_ARG:
385 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
386 break;
387 case Y_STR_ARG:
388 case Y_MAYBE_STR_ARG:
389 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
390 break;
391 }
392 first = 0;
393 }
394
395 return LY_SUCCESS;
396}
397
398/**
399 * @brief Parse extension instance.
400 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100401 * @param[in] ctx parser context.
402 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100403 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200404 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
405 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200406 * @return LY_ERR values.
407 */
408static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200409lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200410 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200411{
412 struct lysp_ext_instance *e;
413
Michal Vaskob36053d2020-03-26 15:49:30 +0100414 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200415
416 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200417 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100418 e->parent_stmt = insubstmt;
419 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200420 e->parsed = NULL;
Radek Krejci335332a2019-09-05 13:03:35 +0200421 /* TODO (duplicate) e->child = stmt->child; */
422
423 /* get optional argument */
424 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200425 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200426 }
427
428 return LY_SUCCESS;
429}
430
431/**
432 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
433 * description, etc...
434 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100435 * @param[in] ctx parser context.
436 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200437 * @param[in] substmt_index Index of this substatement.
438 * @param[in,out] value Place to store the parsed value.
439 * @param[in] arg Type of the YANG keyword argument (of the value).
440 * @param[in,out] exts Extension instances to add to.
441 *
442 * @return LY_ERR values.
443 */
444static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200445lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
446 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200447{
Radek Krejci335332a2019-09-05 13:03:35 +0200448 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200449 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200450 return LY_EVALID;
451 }
452
453 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200454 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200455
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100456 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
457 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200458 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100459 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200460 break;
461 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200462 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200463 return LY_EVALID;
464 }
465 }
466 return LY_SUCCESS;
467}
468
469/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200470 * @brief Parse a qname that can have more instances such as if-feature.
471 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100472 * @param[in] ctx parser context.
473 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200474 * @param[in,out] qnames Parsed qnames to add to.
475 * @param[in] arg Type of the expected argument.
476 * @param[in,out] exts Extension instances to add to.
477 *
478 * @return LY_ERR values.
479 */
480static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200481lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
482 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200483{
484 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200485
486 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
487
488 /* allocate new pointer */
489 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
490 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100491 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200492
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100493 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
494 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200495 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100496 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200497 break;
498 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200499 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200500 return LY_EVALID;
501 }
502 }
503 return LY_SUCCESS;
504}
505
506/**
Radek Krejci335332a2019-09-05 13:03:35 +0200507 * @brief Parse a generic text field that can have more instances such as base.
508 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100509 * @param[in] ctx parser context.
510 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200511 * @param[in,out] texts Parsed values to add to.
512 * @param[in] arg Type of the expected argument.
513 * @param[in,out] exts Extension instances to add to.
514 *
515 * @return LY_ERR values.
516 */
517static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200518lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
519 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200520{
521 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200522
523 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
524
525 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100526 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200527 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200528
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100529 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
530 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200531 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100532 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200533 break;
534 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200535 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200536 return LY_EVALID;
537 }
538 }
539 return LY_SUCCESS;
540}
541
542/**
543 * @brief Parse the status statement.
544 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100545 * @param[in] ctx parser context.
546 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200547 * @param[in,out] flags Flags to add to.
548 * @param[in,out] exts Extension instances to add to.
549 *
550 * @return LY_ERR values.
551 */
552static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200553lysp_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 +0200554{
555 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200556
557 if (*flags & LYS_STATUS_MASK) {
558 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
559 return LY_EVALID;
560 }
561
562 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
563 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100564 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200565 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100566 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200567 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100568 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200569 *flags |= LYS_STATUS_OBSLT;
570 } else {
571 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
572 return LY_EVALID;
573 }
574
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100575 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
576 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200577 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100578 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200579 break;
580 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200581 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200582 return LY_EVALID;
583 }
584 }
585 return LY_SUCCESS;
586}
587
588/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100589 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200590 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100591 * @param[in] ctx parser context.
592 * @param[in] stmt Source statement data from the parsed extension instance.
593 * @param[in,out] when_p When pointer to parse to.
594 *
595 * @return LY_ERR values.
596 */
597static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200598lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100599{
600 LY_ERR ret = LY_SUCCESS;
601 struct lysp_when *when;
602
603 if (*when_p) {
604 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
605 return LY_EVALID;
606 }
607
608 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
609
610 when = calloc(1, sizeof *when);
611 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
612 *when_p = when;
613
614 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
615
616 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
617 switch (child->kw) {
618 case LY_STMT_DESCRIPTION:
619 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
620 break;
621 case LY_STMT_REFERENCE:
622 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
623 break;
624 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100625 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100626 break;
627 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200628 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100629 return LY_EVALID;
630 }
631 }
632 return ret;
633}
634
635/**
636 * @brief Parse the config statement.
637 *
638 * @param[in] ctx parser context.
639 * @param[in] stmt Source statement data from the parsed extension instance.
640 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200641 * @param[in,out] exts Extension instances to add to.
642 *
643 * @return LY_ERR values.
644 */
645static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200646lysp_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 +0200647{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100648 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200649
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100650 if (*flags & LYS_CONFIG_MASK) {
651 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
652 return LY_EVALID;
653 }
654
655 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
656 arg_len = strlen(stmt->arg);
657 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
658 *flags |= LYS_CONFIG_W;
659 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
660 *flags |= LYS_CONFIG_R;
661 } else {
662 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
663 return LY_EVALID;
664 }
665
666 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
667 switch (child->kw) {
668 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100669 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100670 break;
671 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200672 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100673 return LY_EVALID;
674 }
675 }
676
677 return LY_SUCCESS;
678}
679
680/**
681 * @brief Parse the mandatory statement.
682 *
683 * @param[in] ctx parser context.
684 * @param[in] stmt Source statement data from the parsed extension instance.
685 * @param[in,out] flags Flags to add to.
686 * @param[in,out] exts Extension instances to add to.
687 *
688 * @return LY_ERR values.
689 */
690static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200691lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200692 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100693{
694 size_t arg_len;
695
696 if (*flags & LYS_MAND_MASK) {
697 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
698 return LY_EVALID;
699 }
700
701 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
702 arg_len = strlen(stmt->arg);
703 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
704 *flags |= LYS_MAND_TRUE;
705 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
706 *flags |= LYS_MAND_FALSE;
707 } else {
708 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
709 return LY_EVALID;
710 }
711
712 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
713 switch (child->kw) {
714 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100715 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100716 break;
717 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200718 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100719 return LY_EVALID;
720 }
721 }
722
723 return LY_SUCCESS;
724}
725
726/**
727 * @brief Parse a restriction such as range or length.
728 *
729 * @param[in] ctx parser context.
730 * @param[in] stmt Source statement data from the parsed extension instance.
731 * @param[in,out] exts Extension instances to add to.
732 *
733 * @return LY_ERR values.
734 */
735static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200736lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100737{
Radek Krejci335332a2019-09-05 13:03:35 +0200738 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200739 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100740 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200741
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100742 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
743 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200744 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100745 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200746 break;
747 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100748 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200749 break;
750 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100751 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200752 break;
753 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100754 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200755 break;
756 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100757 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200758 break;
759 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200760 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200761 return LY_EVALID;
762 }
763 }
764 return LY_SUCCESS;
765}
766
767/**
768 * @brief Parse a restriction that can have more instances such as must.
769 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100770 * @param[in] ctx parser context.
771 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200772 * @param[in,out] restrs Restrictions to add to.
773 *
774 * @return LY_ERR values.
775 */
776static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200777lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200778{
779 struct lysp_restr *restr;
780
Michal Vaskob36053d2020-03-26 15:49:30 +0100781 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100782 return lysp_stmt_restr(ctx, stmt, restr);
783}
784
785/**
786 * @brief Parse the anydata or anyxml statement.
787 *
788 * @param[in] ctx parser context.
789 * @param[in] stmt Source statement data from the parsed extension instance.
790 * @param[in,out] siblings Siblings to add to.
791 *
792 * @return LY_ERR values.
793 */
794static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200795lysp_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 +0100796{
797 struct lysp_node_anydata *any;
798
799 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
800
801 /* create new structure and insert into siblings */
802 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
803
804 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
805 any->parent = parent;
806
807 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
808
809 /* parse substatements */
810 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
811 switch (child->kw) {
812 case LY_STMT_CONFIG:
813 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
814 break;
815 case LY_STMT_DESCRIPTION:
816 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
817 break;
818 case LY_STMT_IF_FEATURE:
819 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
820 break;
821 case LY_STMT_MANDATORY:
822 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
823 break;
824 case LY_STMT_MUST:
825 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
826 break;
827 case LY_STMT_REFERENCE:
828 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
829 break;
830 case LY_STMT_STATUS:
831 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
832 break;
833 case LY_STMT_WHEN:
834 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
835 break;
836 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100837 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100838 break;
839 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200840 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
841 (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 +0100842 return LY_EVALID;
843 }
844 }
845
846 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200847}
848
849/**
850 * @brief Parse the value or position statement. Substatement of type enum statement.
851 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100852 * @param[in] ctx parser context.
853 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200854 * @param[in,out] value Value to write to.
855 * @param[in,out] flags Flags to write to.
856 * @param[in,out] exts Extension instances to add to.
857 *
858 * @return LY_ERR values.
859 */
860static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200861lysp_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 +0200862 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200863{
864 size_t arg_len;
865 char *ptr = NULL;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200866 long long int num = 0;
867 unsigned long long int unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200868
869 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200870 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200871 return LY_EVALID;
872 }
873 *flags |= LYS_SET_VALUE;
874
875 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
876
877 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100878 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
879 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200880 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200881 goto error;
882 }
883
884 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100885 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200886 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200887 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200888 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200889 goto error;
890 }
891 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200892 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200893 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200894 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200895 goto error;
896 }
897 }
898 /* we have not parsed the whole argument */
899 if ((size_t)(ptr - stmt->arg) != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200900 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200901 goto error;
902 }
903 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200904 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200905 goto error;
906 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100907 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200908 *value = num;
909 } else {
910 *value = unum;
911 }
912
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100913 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
914 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200915 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100916 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 +0200917 break;
918 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200919 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200920 return LY_EVALID;
921 }
922 }
923 return LY_SUCCESS;
924
925error:
926 return LY_EVALID;
927}
928
929/**
930 * @brief Parse the enum or bit statement. Substatement of type statement.
931 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100932 * @param[in] ctx parser context.
933 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200934 * @param[in,out] enums Enums or bits to add to.
935 *
936 * @return LY_ERR values.
937 */
938static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200939lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +0200940{
941 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200942
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100943 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 +0200944
Michal Vaskob36053d2020-03-26 15:49:30 +0100945 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200946
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100947 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +0200948 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
949 } /* else nothing specific for YANG_BIT */
950
Radek Krejci011e4aa2020-09-04 15:22:31 +0200951 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +0200952 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +0200953
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100954 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
955 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200956 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100957 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200958 break;
959 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +0200960 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100961 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200962 break;
963 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100964 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200965 break;
966 case LY_STMT_STATUS:
967 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
968 break;
969 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +0200970 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
971 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100972 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200973 break;
974 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +0200975 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
976 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100977 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200978 break;
979 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100980 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200981 break;
982 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200983 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200984 return LY_EVALID;
985 }
986 }
Michal Vasko193dacd2022-10-13 08:43:05 +0200987
Radek Krejci335332a2019-09-05 13:03:35 +0200988 return LY_SUCCESS;
989}
990
991/**
992 * @brief Parse the fraction-digits statement. Substatement of type statement.
993 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100994 * @param[in] ctx parser context.
995 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200996 * @param[in,out] fracdig Value to write to.
997 * @param[in,out] exts Extension instances to add to.
998 *
999 * @return LY_ERR values.
1000 */
1001static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001002lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001003 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001004{
1005 char *ptr;
1006 size_t arg_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001007 unsigned long long int num;
Radek Krejci335332a2019-09-05 13:03:35 +02001008
1009 if (*fracdig) {
1010 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1011 return LY_EVALID;
1012 }
1013
1014 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1015 arg_len = strlen(stmt->arg);
1016 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1017 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1018 return LY_EVALID;
1019 }
1020
1021 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001022 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001023 /* we have not parsed the whole argument */
1024 if ((size_t)(ptr - stmt->arg) != arg_len) {
1025 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1026 return LY_EVALID;
1027 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001028 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001029 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1030 return LY_EVALID;
1031 }
1032 *fracdig = num;
1033
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001034 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1035 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001036 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001037 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001038 break;
1039 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001040 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001041 return LY_EVALID;
1042 }
1043 }
1044 return LY_SUCCESS;
1045}
1046
1047/**
1048 * @brief Parse the require-instance statement. Substatement of type statement.
1049 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001050 * @param[in] ctx parser context.
1051 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001052 * @param[in,out] reqinst Value to write to.
1053 * @param[in,out] flags Flags to write to.
1054 * @param[in,out] exts Extension instances to add to.
1055 *
1056 * @return LY_ERR values.
1057 */
1058static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001059lysp_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 +02001060 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001061{
1062 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001063
1064 if (*flags & LYS_SET_REQINST) {
1065 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1066 return LY_EVALID;
1067 }
1068 *flags |= LYS_SET_REQINST;
1069
1070 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1071 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001072 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001073 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001074 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001075 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1076 return LY_EVALID;
1077 }
1078
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001079 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1080 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001081 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001082 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001083 break;
1084 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001085 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001086 return LY_EVALID;
1087 }
1088 }
1089 return LY_SUCCESS;
1090}
1091
1092/**
1093 * @brief Parse the modifier statement. Substatement of type pattern statement.
1094 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001095 * @param[in] ctx parser context.
1096 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001097 * @param[in,out] pat Value to write to.
1098 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001099 * @return LY_ERR values.
1100 */
1101static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001102lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001103 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001104{
1105 size_t arg_len;
1106 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001107
Radek Krejcif13b87b2020-12-01 22:02:17 +01001108 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001109 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1110 return LY_EVALID;
1111 }
1112
1113 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1114 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001115 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001116 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1117 return LY_EVALID;
1118 }
1119
1120 /* replace the value in the dictionary */
1121 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001122 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001123 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001124 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001125
Radek Krejcif13b87b2020-12-01 22:02:17 +01001126 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1127 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001128 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001129
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001130 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1131 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001132 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001133 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001134 break;
1135 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001136 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001137 return LY_EVALID;
1138 }
1139 }
1140 return LY_SUCCESS;
1141}
1142
1143/**
1144 * @brief Parse the pattern statement. Substatement of type statement.
1145 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001146 * @param[in] ctx parser context.
1147 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001148 * @param[in,out] patterns Restrictions to add to.
1149 *
1150 * @return LY_ERR values.
1151 */
1152static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001153lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001154{
1155 char *buf;
1156 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001157 struct lysp_restr *restr;
1158
1159 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001160 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001161 arg_len = strlen(stmt->arg);
1162
1163 /* add special meaning first byte */
1164 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001165 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001166 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001167 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001168 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001169 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001170 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001171
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001172 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1173 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001174 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001175 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001176 break;
1177 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001178 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001179 break;
1180 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001181 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001182 break;
1183 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001184 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001185 break;
1186 case LY_STMT_MODIFIER:
1187 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001188 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001189 break;
1190 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001191 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001192 break;
1193 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001194 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001195 return LY_EVALID;
1196 }
1197 }
1198 return LY_SUCCESS;
1199}
1200
1201/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001202 * @brief Parse the deviate statement. Substatement of deviation statement.
1203 *
1204 * @param[in] ctx parser context.
1205 * @param[in] stmt Source statement data from the parsed extension instance.
1206 * @param[in,out] devs Array of deviates to add to.
1207 * @param[in,out] exts Extension instances to add to.
1208 * @return LY_ERR values.
1209 */
1210static LY_ERR
1211lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1212{
1213 (void)stmt;
1214 (void)devs;
1215 (void)exts;
1216
1217 /* TODO */
1218 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1219 return LY_EINVAL;
1220}
1221
1222/**
1223 * @brief Parse the deviation statement.
1224 *
1225 * @param[in] ctx parser context.
1226 * @param[in] stmt Source statement data from the parsed extension instance.
1227 * @param[in,out] deviations Array of deviations to add to.
1228 * @return LY_ERR values.
1229 */
1230static LY_ERR
1231lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1232{
1233 struct lysp_deviation *dev;
1234
1235 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1236
1237 /* store nodeid */
1238 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1239 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1240
1241 /* parse substatements */
1242 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1243 switch (child->kw) {
1244 case LY_STMT_DESCRIPTION:
1245 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1246 break;
1247 case LY_STMT_DEVIATE:
1248 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1249 break;
1250 case LY_STMT_REFERENCE:
1251 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1252 break;
1253 case LY_STMT_EXTENSION_INSTANCE:
1254 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1255 break;
1256 default:
1257 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1258 return LY_EVALID;
1259 }
1260 }
1261
1262 return LY_SUCCESS;
1263}
1264
1265/**
1266 * @brief Parse the yang-version statement.
1267 *
1268 * @param[in] ctx parser context.
1269 * @param[in] stmt Source statement data from the parsed extension instance.
1270 * @param[out] version Version to write to.
1271 * @param[in,out] exts Extension instances to add to.
1272 * @return LY_ERR values.
1273 */
1274static LY_ERR
1275lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1276{
1277 if (*version) {
1278 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1279 return LY_EVALID;
1280 }
1281
1282 /* store flag */
1283 if (!strcmp(stmt->arg, "1")) {
1284 *version = LYS_VERSION_1_0;
1285 } else if (!strcmp(stmt->arg, "1.1")) {
1286 *version = LYS_VERSION_1_1;
1287 } else {
1288 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yang-version");
1289 return LY_EVALID;
1290 }
1291
1292 /* parse substatements */
1293 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1294 switch (child->kw) {
1295 case LY_STMT_EXTENSION_INSTANCE:
1296 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1297 break;
1298 default:
1299 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1300 return LY_EVALID;
1301 }
1302 }
1303
1304 return LY_SUCCESS;
1305}
1306
1307/**
1308 * @brief Parse the module statement.
1309 *
1310 * @param[in] ctx parser context.
1311 * @param[in] stmt Source statement data from the parsed extension instance.
1312 * @param[in,out] mod Module to fill.
1313 * @return LY_ERR values.
1314 */
1315static LY_ERR
1316lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1317{
1318 (void)stmt;
1319 (void)mod;
1320
1321 /* TODO */
1322 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1323 return LY_EINVAL;
1324}
1325
1326/**
1327 * @brief Parse the submodule statement.
1328 *
1329 * @param[in] ctx parser context.
1330 * @param[in] stmt Source statement data from the parsed extension instance.
1331 * @param[in,out] submod Module to fill.
1332 * @return LY_ERR values.
1333 */
1334static LY_ERR
1335lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1336{
1337 (void)stmt;
1338 (void)submod;
1339
1340 /* TODO */
1341 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1342 return LY_EINVAL;
1343}
1344
1345/**
1346 * @brief Parse the yin-element statement. Substatement of argument statement.
1347 *
1348 * @param[in] ctx parser context.
1349 * @param[in] stmt Source statement data from the parsed extension instance.
1350 * @param[in,out] flags Flags to write to.
1351 * @param[in,out] exts Extension instances to add to.
1352 * @return LY_ERR values.
1353 */
1354static LY_ERR
1355lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1356{
1357 if (*flags & LYS_YINELEM_MASK) {
1358 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1359 return LY_EVALID;
1360 }
1361
1362 /* store flag */
1363 if (!strcmp(stmt->arg, "true")) {
1364 *flags |= LYS_YINELEM_TRUE;
1365 } else if (!strcmp(stmt->arg, "false")) {
1366 *flags |= LYS_YINELEM_FALSE;
1367 } else {
1368 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yin-element");
1369 return LY_EVALID;
1370 }
1371
1372 /* parse substatements */
1373 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1374 switch (child->kw) {
1375 case LY_STMT_EXTENSION_INSTANCE:
1376 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1377 break;
1378 default:
1379 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1380 return LY_EVALID;
1381 }
1382 }
1383
1384 return LY_SUCCESS;
1385}
1386
1387/**
1388 * @brief Parse the argument statement. Substatement of extension statement.
1389 *
1390 * @param[in] ctx parser context.
1391 * @param[in] stmt Source statement data from the parsed extension instance.
1392 * @param[in,out] ex Extension to fill.
1393 * @return LY_ERR values.
1394 */
1395static LY_ERR
1396lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1397{
1398 if (ex->argname) {
1399 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1400 return LY_EVALID;
1401 }
1402
1403 /* store argument name */
1404 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1405 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1406
1407 /* parse substatements */
1408 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1409 switch (child->kw) {
1410 case LY_STMT_YIN_ELEMENT:
1411 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1412 break;
1413 case LY_STMT_EXTENSION_INSTANCE:
1414 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1415 break;
1416 default:
1417 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1418 return LY_EVALID;
1419 }
1420 }
1421
1422 return LY_SUCCESS;
1423}
1424
1425/**
1426 * @brief Parse the extension statement.
1427 *
1428 * @param[in] ctx parser context.
1429 * @param[in] stmt Source statement data from the parsed extension instance.
1430 * @param[in,out] extensions Array of extensions to add to.
1431 * @return LY_ERR values.
1432 */
1433static LY_ERR
1434lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1435{
1436 struct lysp_ext *ex;
1437
1438 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1439
1440 /* store name */
1441 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1442 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1443
1444 /* parse substatements */
1445 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1446 switch (child->kw) {
1447 case LY_STMT_DESCRIPTION:
1448 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1449 break;
1450 case LY_STMT_REFERENCE:
1451 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1452 break;
1453 case LY_STMT_STATUS:
1454 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1455 break;
1456 case LY_STMT_ARGUMENT:
1457 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1458 break;
1459 case LY_STMT_EXTENSION_INSTANCE:
1460 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1461 break;
1462 default:
1463 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1464 return LY_EVALID;
1465 }
1466 }
1467
1468 return LY_SUCCESS;
1469}
1470
1471/**
1472 * @brief Parse the feature statement.
1473 *
1474 * @param[in] ctx parser context.
1475 * @param[in] stmt Source statement data from the parsed extension instance.
1476 * @param[in,out] features Array of features to add to.
1477 * @return LY_ERR values.
1478 */
1479static LY_ERR
1480lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1481{
1482 struct lysp_feature *feat;
1483
1484 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1485
1486 /* store name */
1487 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1488 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1489
1490 /* parse substatements */
1491 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1492 switch (child->kw) {
1493 case LY_STMT_DESCRIPTION:
1494 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1495 break;
1496 case LY_STMT_IF_FEATURE:
1497 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1498 break;
1499 case LY_STMT_REFERENCE:
1500 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1501 break;
1502 case LY_STMT_STATUS:
1503 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1504 break;
1505 case LY_STMT_EXTENSION_INSTANCE:
1506 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1507 break;
1508 default:
1509 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1510 return LY_EVALID;
1511 }
1512 }
1513
1514 return LY_SUCCESS;
1515}
1516
1517/**
1518 * @brief Parse the identity statement.
1519 *
1520 * @param[in] ctx parser context.
1521 * @param[in] stmt Source statement data from the parsed extension instance.
1522 * @param[in,out] identities Array of identities to add to.
1523 * @return LY_ERR values.
1524 */
1525static LY_ERR
1526lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1527{
1528 struct lysp_ident *ident;
1529
1530 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1531
1532 /* store name */
1533 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1534 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1535
1536 /* parse substatements */
1537 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1538 switch (child->kw) {
1539 case LY_STMT_DESCRIPTION:
1540 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1541 break;
1542 case LY_STMT_IF_FEATURE:
1543 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1544 break;
1545 case LY_STMT_REFERENCE:
1546 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1547 break;
1548 case LY_STMT_STATUS:
1549 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1550 break;
1551 case LY_STMT_BASE:
1552 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1553 break;
1554 case LY_STMT_EXTENSION_INSTANCE:
1555 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1556 break;
1557 default:
1558 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1559 return LY_EVALID;
1560 }
1561 }
1562
1563 return LY_SUCCESS;
1564}
1565
1566/**
1567 * @brief Parse the import statement.
1568 *
1569 * @param[in] ctx parser context.
1570 * @param[in] stmt Source statement data from the parsed extension instance.
1571 * @param[in,out] imports Array of imports to add to.
1572 * @return LY_ERR values.
1573 */
1574static LY_ERR
1575lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1576{
1577 struct lysp_import *imp;
1578 const char *str = NULL;
1579
1580 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1581
1582 /* store name */
1583 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1584 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1585
1586 /* parse substatements */
1587 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1588 switch (child->kw) {
1589 case LY_STMT_PREFIX:
1590 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1591 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1592 break;
1593 case LY_STMT_DESCRIPTION:
1594 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1595 break;
1596 case LY_STMT_REFERENCE:
1597 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1598 break;
1599 case LY_STMT_REVISION_DATE:
1600 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1601 strcpy(imp->rev, str);
1602 lydict_remove(PARSER_CTX(ctx), str);
1603 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1604 break;
1605 case LY_STMT_EXTENSION_INSTANCE:
1606 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1607 break;
1608 default:
1609 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1610 return LY_EVALID;
1611 }
1612 }
1613
1614 return LY_SUCCESS;
1615}
1616
1617/**
1618 * @brief Parse the include statement.
1619 *
1620 * @param[in] ctx parser context.
1621 * @param[in] stmt Source statement data from the parsed extension instance.
1622 * @param[in,out] includes Array of identities to add to.
1623 * @return LY_ERR values.
1624 */
1625static LY_ERR
1626lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1627{
1628 struct lysp_include *inc;
1629 const char *str = NULL;
1630
1631 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1632
1633 /* store name */
1634 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1635 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1636
1637 /* parse substatements */
1638 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1639 switch (child->kw) {
1640 case LY_STMT_DESCRIPTION:
1641 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1642 break;
1643 case LY_STMT_REFERENCE:
1644 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1645 break;
1646 case LY_STMT_REVISION_DATE:
1647 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1648 strcpy(inc->rev, str);
1649 lydict_remove(PARSER_CTX(ctx), str);
1650 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1651 break;
1652 case LY_STMT_EXTENSION_INSTANCE:
1653 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1654 break;
1655 default:
1656 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1657 return LY_EVALID;
1658 }
1659 }
1660
1661 return LY_SUCCESS;
1662}
1663
1664/**
1665 * @brief Parse the revision statement.
1666 *
1667 * @param[in] ctx parser context.
1668 * @param[in] stmt Source statement data from the parsed extension instance.
1669 * @param[in,out] includes Array of identities to add to.
1670 * @return LY_ERR values.
1671 */
1672static LY_ERR
1673lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1674{
1675 struct lysp_revision *rev;
1676
1677 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1678
1679 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001680 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001681 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001682
1683 /* parse substatements */
1684 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1685 switch (child->kw) {
1686 case LY_STMT_DESCRIPTION:
1687 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1688 break;
1689 case LY_STMT_REFERENCE:
1690 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1691 break;
1692 case LY_STMT_EXTENSION_INSTANCE:
1693 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1694 break;
1695 default:
1696 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1697 return LY_EVALID;
1698 }
1699 }
1700
1701 return LY_SUCCESS;
1702}
1703
1704/**
Radek Krejci335332a2019-09-05 13:03:35 +02001705 * @brief Parse the type statement.
1706 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001707 * @param[in] ctx parser context.
1708 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001709 * @param[in,out] type Type to wrote to.
1710 *
1711 * @return LY_ERR values.
1712 */
1713static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001714lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001715{
1716 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001717 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001718 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001719
1720 if (type->name) {
1721 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1722 return LY_EVALID;
1723 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001724
1725 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001726 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001727 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001728
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001729 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1730 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001731 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001732 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001733 type->flags |= LYS_SET_BASE;
1734 break;
1735 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001736 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001737 type->flags |= LYS_SET_BIT;
1738 break;
1739 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001740 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001741 type->flags |= LYS_SET_ENUM;
1742 break;
1743 case LY_STMT_FRACTION_DIGITS:
1744 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1745 type->flags |= LYS_SET_FRDIGITS;
1746 break;
1747 case LY_STMT_LENGTH:
1748 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001749 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001750 return LY_EVALID;
1751 }
1752 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001753 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001754
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001755 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001756 type->flags |= LYS_SET_LENGTH;
1757 break;
1758 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001759 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001760 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001761 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001762 lydict_remove(PARSER_CTX(ctx), str_path);
1763 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001764 type->flags |= LYS_SET_PATH;
1765 break;
1766 case LY_STMT_PATTERN:
1767 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1768 type->flags |= LYS_SET_PATTERN;
1769 break;
1770 case LY_STMT_RANGE:
1771 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001772 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001773 return LY_EVALID;
1774 }
1775 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001776 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001777
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001778 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001779 type->flags |= LYS_SET_RANGE;
1780 break;
1781 case LY_STMT_REQUIRE_INSTANCE:
1782 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001783 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001784 break;
1785 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001786 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001787 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1788 type->flags |= LYS_SET_TYPE;
1789 break;
1790 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001791 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001792 break;
1793 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001794 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001795 return LY_EVALID;
1796 }
1797 }
1798 return LY_SUCCESS;
1799}
1800
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001801/**
1802 * @brief Parse the leaf statement.
1803 *
1804 * @param[in] ctx parser context.
1805 * @param[in] stmt Source statement data from the parsed extension instance.
1806 * @param[in] parent Parent node to connect to (not into).
1807 * @param[in,out] siblings Siblings to add to.
1808 *
1809 * @return LY_ERR values.
1810 */
1811static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001812lysp_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 +01001813{
1814 struct lysp_node_leaf *leaf;
1815
1816 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1817
1818 /* create new leaf structure */
1819 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1820 leaf->nodetype = LYS_LEAF;
1821 leaf->parent = parent;
1822
1823 /* get name */
1824 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1825
1826 /* parse substatements */
1827 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1828 switch (child->kw) {
1829 case LY_STMT_CONFIG:
1830 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1831 break;
1832 case LY_STMT_DEFAULT:
1833 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 +01001834 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001835 break;
1836 case LY_STMT_DESCRIPTION:
1837 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1838 break;
1839 case LY_STMT_IF_FEATURE:
1840 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1841 break;
1842 case LY_STMT_MANDATORY:
1843 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1844 break;
1845 case LY_STMT_MUST:
1846 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1847 break;
1848 case LY_STMT_REFERENCE:
1849 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1850 break;
1851 case LY_STMT_STATUS:
1852 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1853 break;
1854 case LY_STMT_TYPE:
1855 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1856 break;
1857 case LY_STMT_UNITS:
1858 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1859 break;
1860 case LY_STMT_WHEN:
1861 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1862 break;
1863 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001864 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001865 break;
1866 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001867 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001868 return LY_EVALID;
1869 }
1870 }
1871
1872 /* mandatory substatements */
1873 if (!leaf->type.name) {
1874 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1875 return LY_EVALID;
1876 }
1877
1878 return LY_SUCCESS;
1879}
1880
1881/**
1882 * @brief Parse the max-elements statement.
1883 *
1884 * @param[in] ctx parser context.
1885 * @param[in] stmt Source statement data from the parsed extension instance.
1886 * @param[in,out] max Value to write to.
1887 * @param[in,out] flags Flags to write to.
1888 * @param[in,out] exts Extension instances to add to.
1889 *
1890 * @return LY_ERR values.
1891 */
1892static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001893lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
1894 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001895{
1896 size_t arg_len;
1897 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001898 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001899
1900 if (*flags & LYS_SET_MAX) {
1901 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1902 return LY_EVALID;
1903 }
1904 *flags |= LYS_SET_MAX;
1905
1906 /* get value */
1907 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1908 arg_len = strlen(stmt->arg);
1909
1910 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1911 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1912 return LY_EVALID;
1913 }
1914
1915 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1916 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001917 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001918 /* we have not parsed the whole argument */
1919 if ((size_t)(ptr - stmt->arg) != arg_len) {
1920 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1921 return LY_EVALID;
1922 }
1923 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1924 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1925 return LY_EVALID;
1926 }
1927
1928 *max = num;
1929 } else {
1930 /* unbounded */
1931 *max = 0;
1932 }
1933
1934 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1935 switch (child->kw) {
1936 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001937 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001938 break;
1939 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001940 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001941 return LY_EVALID;
1942 }
1943 }
1944
1945 return LY_SUCCESS;
1946}
1947
1948/**
1949 * @brief Parse the min-elements statement.
1950 *
1951 * @param[in] ctx parser context.
1952 * @param[in] stmt Source statement data from the parsed extension instance.
1953 * @param[in,out] min Value to write to.
1954 * @param[in,out] flags Flags to write to.
1955 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001956 * @return LY_ERR values.
1957 */
1958static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001959lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
1960 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001961{
1962 size_t arg_len;
1963 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001964 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001965
1966 if (*flags & LYS_SET_MIN) {
1967 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
1968 return LY_EVALID;
1969 }
1970 *flags |= LYS_SET_MIN;
1971
1972 /* get value */
1973 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1974 arg_len = strlen(stmt->arg);
1975
1976 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
1977 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1978 return LY_EVALID;
1979 }
1980
1981 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001982 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001983 /* we have not parsed the whole argument */
1984 if ((size_t)(ptr - stmt->arg) != arg_len) {
1985 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1986 return LY_EVALID;
1987 }
1988 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1989 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
1990 return LY_EVALID;
1991 }
1992 *min = num;
1993
1994 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1995 switch (child->kw) {
1996 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001997 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001998 break;
1999 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002000 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002001 return LY_EVALID;
2002 }
2003 }
2004
2005 return LY_SUCCESS;
2006}
2007
2008/**
2009 * @brief Parse the ordered-by statement.
2010 *
2011 * @param[in] ctx parser context.
2012 * @param[in] stmt Source statement data from the parsed extension instance.
2013 * @param[in,out] flags Flags to write to.
2014 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002015 * @return LY_ERR values.
2016 */
2017static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002018lysp_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 +01002019{
2020 size_t arg_len;
2021
2022 if (*flags & LYS_ORDBY_MASK) {
2023 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2024 return LY_EVALID;
2025 }
2026
2027 /* get value */
2028 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2029 arg_len = strlen(stmt->arg);
2030 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2031 *flags |= LYS_MAND_TRUE;
2032 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2033 *flags |= LYS_MAND_FALSE;
2034 } else {
2035 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2036 return LY_EVALID;
2037 }
2038
2039 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2040 switch (child->kw) {
2041 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002042 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002043 break;
2044 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002045 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002046 return LY_EVALID;
2047 }
2048 }
2049
2050 return LY_SUCCESS;
2051}
2052
2053/**
2054 * @brief Parse the leaf-list statement.
2055 *
2056 * @param[in] ctx parser context.
2057 * @param[in] stmt Source statement data from the parsed extension instance.
2058 * @param[in] parent Parent node to connect to (not into).
2059 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002060 * @return LY_ERR values.
2061 */
2062static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002063lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002064 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002065{
2066 struct lysp_node_leaflist *llist;
2067
2068 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2069
2070 /* create new leaf-list structure */
2071 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2072 llist->nodetype = LYS_LEAFLIST;
2073 llist->parent = parent;
2074
2075 /* get name */
2076 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2077
2078 /* parse substatements */
2079 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2080 switch (child->kw) {
2081 case LY_STMT_CONFIG:
2082 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2083 break;
2084 case LY_STMT_DEFAULT:
2085 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2086 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2087 break;
2088 case LY_STMT_DESCRIPTION:
2089 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2090 break;
2091 case LY_STMT_IF_FEATURE:
2092 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2093 break;
2094 case LY_STMT_MAX_ELEMENTS:
2095 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2096 break;
2097 case LY_STMT_MIN_ELEMENTS:
2098 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2099 break;
2100 case LY_STMT_MUST:
2101 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2102 break;
2103 case LY_STMT_ORDERED_BY:
2104 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2105 break;
2106 case LY_STMT_REFERENCE:
2107 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2108 break;
2109 case LY_STMT_STATUS:
2110 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2111 break;
2112 case LY_STMT_TYPE:
2113 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2114 break;
2115 case LY_STMT_UNITS:
2116 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2117 break;
2118 case LY_STMT_WHEN:
2119 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2120 break;
2121 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002122 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002123 break;
2124 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002125 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002126 return LY_EVALID;
2127 }
2128 }
2129
2130 /* mandatory substatements */
2131 if (!llist->type.name) {
2132 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2133 return LY_EVALID;
2134 }
2135
2136 return LY_SUCCESS;
2137}
2138
2139/**
2140 * @brief Parse the refine statement.
2141 *
2142 * @param[in] ctx parser context.
2143 * @param[in] stmt Source statement data from the parsed extension instance.
2144 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002145 * @return LY_ERR values.
2146 */
2147static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002148lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002149{
2150 struct lysp_refine *rf;
2151
2152 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2153
2154 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2155
2156 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2157
2158 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2159 switch (child->kw) {
2160 case LY_STMT_CONFIG:
2161 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2162 break;
2163 case LY_STMT_DEFAULT:
2164 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2165 break;
2166 case LY_STMT_DESCRIPTION:
2167 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2168 break;
2169 case LY_STMT_IF_FEATURE:
2170 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2171 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2172 break;
2173 case LY_STMT_MAX_ELEMENTS:
2174 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2175 break;
2176 case LY_STMT_MIN_ELEMENTS:
2177 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2178 break;
2179 case LY_STMT_MUST:
2180 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2181 break;
2182 case LY_STMT_MANDATORY:
2183 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2184 break;
2185 case LY_STMT_REFERENCE:
2186 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2187 break;
2188 case LY_STMT_PRESENCE:
2189 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2190 break;
2191 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002192 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002193 break;
2194 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002195 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002196 return LY_EVALID;
2197 }
2198 }
2199
2200 return LY_SUCCESS;
2201}
2202
2203/**
2204 * @brief Parse the typedef statement.
2205 *
2206 * @param[in] ctx parser context.
2207 * @param[in] stmt Source statement data from the parsed extension instance.
2208 * @param[in] parent Parent node to connect to (not into).
2209 * @param[in,out] typedefs Typedefs to add to.
2210 *
2211 * @return LY_ERR values.
2212 */
2213static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002214lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002215 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002216{
2217 struct lysp_tpdf *tpdf;
2218
2219 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2220
2221 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2222
2223 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2224
2225 /* parse substatements */
2226 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2227 switch (child->kw) {
2228 case LY_STMT_DEFAULT:
2229 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 +01002230 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002231 break;
2232 case LY_STMT_DESCRIPTION:
2233 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2234 break;
2235 case LY_STMT_REFERENCE:
2236 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2237 break;
2238 case LY_STMT_STATUS:
2239 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2240 break;
2241 case LY_STMT_TYPE:
2242 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2243 break;
2244 case LY_STMT_UNITS:
2245 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2246 break;
2247 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002248 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002249 break;
2250 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002251 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002252 return LY_EVALID;
2253 }
2254 }
2255
2256 /* mandatory substatements */
2257 if (!tpdf->type.name) {
2258 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2259 return LY_EVALID;
2260 }
2261
2262 /* store data for collision check */
2263 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2264 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2265 }
2266
2267 return LY_SUCCESS;
2268}
2269
2270/**
2271 * @brief Parse the input or output statement.
2272 *
2273 * @param[in] ctx parser context.
2274 * @param[in] stmt Source statement data from the parsed extension instance.
2275 * @param[in] parent Parent node to connect to (not into).
2276 * @param[in,out] inout_p Input/output pointer to write to.
2277 *
2278 * @return LY_ERR values.
2279 */
2280static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002281lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002282 struct lysp_node_action_inout *inout_p)
2283{
2284 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002285 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002286 return LY_EVALID;
2287 }
2288
2289 /* initiate structure */
2290 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2291 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2292 inout_p->parent = parent;
2293
2294 /* parse substatements */
2295 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2296 switch (child->kw) {
2297 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002298 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002299 /* fall through */
2300 case LY_STMT_ANYXML:
2301 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2302 break;
2303 case LY_STMT_CHOICE:
2304 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2305 break;
2306 case LY_STMT_CONTAINER:
2307 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2308 break;
2309 case LY_STMT_LEAF:
2310 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2311 break;
2312 case LY_STMT_LEAF_LIST:
2313 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2314 break;
2315 case LY_STMT_LIST:
2316 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2317 break;
2318 case LY_STMT_USES:
2319 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2320 break;
2321 case LY_STMT_TYPEDEF:
2322 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2323 break;
2324 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002325 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002326 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2327 break;
2328 case LY_STMT_GROUPING:
2329 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2330 break;
2331 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002332 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002333 break;
2334 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002335 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002336 return LY_EVALID;
2337 }
2338 }
2339
2340 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002341 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002342 return LY_EVALID;
2343 }
2344
2345 return LY_SUCCESS;
2346}
2347
2348/**
2349 * @brief Parse the action statement.
2350 *
2351 * @param[in] ctx parser context.
2352 * @param[in] stmt Source statement data from the parsed extension instance.
2353 * @param[in] parent Parent node to connect to (not into).
2354 * @param[in,out] actions Actions to add to.
2355 *
2356 * @return LY_ERR values.
2357 */
2358static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002359lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002360 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002361{
2362 struct lysp_node_action *act;
2363
2364 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2365
2366 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2367
2368 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2369 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2370 act->parent = parent;
2371
2372 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2373 switch (child->kw) {
2374 case LY_STMT_DESCRIPTION:
2375 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2376 break;
2377 case LY_STMT_IF_FEATURE:
2378 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2379 break;
2380 case LY_STMT_REFERENCE:
2381 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2382 break;
2383 case LY_STMT_STATUS:
2384 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2385 break;
2386
2387 case LY_STMT_INPUT:
2388 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2389 break;
2390 case LY_STMT_OUTPUT:
2391 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2392 break;
2393
2394 case LY_STMT_TYPEDEF:
2395 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2396 break;
2397 case LY_STMT_GROUPING:
2398 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2399 break;
2400 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002401 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 +01002402 break;
2403 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002404 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002405 return LY_EVALID;
2406 }
2407 }
2408
2409 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2410 if (!act->input.nodetype) {
2411 act->input.nodetype = LYS_INPUT;
2412 act->input.parent = &act->node;
2413 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2414 }
2415 if (!act->output.nodetype) {
2416 act->output.nodetype = LYS_OUTPUT;
2417 act->output.parent = &act->node;
2418 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2419 }
2420
2421 return LY_SUCCESS;
2422}
2423
2424/**
2425 * @brief Parse the notification statement.
2426 *
2427 * @param[in] ctx parser context.
2428 * @param[in] stmt Source statement data from the parsed extension instance.
2429 * @param[in] parent Parent node to connect to (not into).
2430 * @param[in,out] notifs Notifications to add to.
2431 *
2432 * @return LY_ERR values.
2433 */
2434static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002435lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002436 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002437{
2438 struct lysp_node_notif *notif;
2439
2440 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2441
2442 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2443
2444 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2445 notif->nodetype = LYS_NOTIF;
2446 notif->parent = parent;
2447
2448 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2449 switch (child->kw) {
2450 case LY_STMT_DESCRIPTION:
2451 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2452 break;
2453 case LY_STMT_IF_FEATURE:
2454 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2455 break;
2456 case LY_STMT_REFERENCE:
2457 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2458 break;
2459 case LY_STMT_STATUS:
2460 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2461 break;
2462
2463 case LY_STMT_ANYDATA:
2464 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2465 /* fall through */
2466 case LY_STMT_ANYXML:
2467 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2468 break;
2469 case LY_STMT_CHOICE:
2470 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2471 break;
2472 case LY_STMT_CONTAINER:
2473 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2474 break;
2475 case LY_STMT_LEAF:
2476 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2477 break;
2478 case LY_STMT_LEAF_LIST:
2479 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2480 break;
2481 case LY_STMT_LIST:
2482 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2483 break;
2484 case LY_STMT_USES:
2485 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2486 break;
2487
2488 case LY_STMT_MUST:
2489 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2490 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2491 break;
2492 case LY_STMT_TYPEDEF:
2493 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2494 break;
2495 case LY_STMT_GROUPING:
2496 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2497 break;
2498 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002499 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002500 break;
2501 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002502 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002503 return LY_EVALID;
2504 }
2505 }
2506
2507 return LY_SUCCESS;
2508}
2509
2510/**
2511 * @brief Parse the grouping statement.
2512 *
2513 * @param[in] ctx parser context.
2514 * @param[in] stmt Source statement data from the parsed extension instance.
2515 * @param[in] parent Parent node to connect to (not into).
2516 * @param[in,out] groupings Groupings to add to.
2517 *
2518 * @return LY_ERR values.
2519 */
2520static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002521lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002522 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002523{
2524 struct lysp_node_grp *grp;
2525
2526 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2527
2528 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2529
2530 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2531 grp->nodetype = LYS_GROUPING;
2532 grp->parent = parent;
2533
2534 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2535 switch (child->kw) {
2536 case LY_STMT_DESCRIPTION:
2537 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2538 break;
2539 case LY_STMT_REFERENCE:
2540 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2541 break;
2542 case LY_STMT_STATUS:
2543 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2544 break;
2545
2546 case LY_STMT_ANYDATA:
2547 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2548 /* fall through */
2549 case LY_STMT_ANYXML:
2550 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2551 break;
2552 case LY_STMT_CHOICE:
2553 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2554 break;
2555 case LY_STMT_CONTAINER:
2556 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2557 break;
2558 case LY_STMT_LEAF:
2559 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2560 break;
2561 case LY_STMT_LEAF_LIST:
2562 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2563 break;
2564 case LY_STMT_LIST:
2565 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2566 break;
2567 case LY_STMT_USES:
2568 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2569 break;
2570
2571 case LY_STMT_TYPEDEF:
2572 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2573 break;
2574 case LY_STMT_ACTION:
2575 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2576 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2577 break;
2578 case LY_STMT_GROUPING:
2579 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2580 break;
2581 case LY_STMT_NOTIFICATION:
2582 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2583 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2584 break;
2585 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002586 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002587 break;
2588 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002589 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002590 return LY_EVALID;
2591 }
2592 }
2593
2594 return LY_SUCCESS;
2595}
2596
2597/**
2598 * @brief Parse the augment statement.
2599 *
2600 * @param[in] ctx parser context.
2601 * @param[in] stmt Source statement data from the parsed extension instance.
2602 * @param[in] parent Parent node to connect to (not into).
2603 * @param[in,out] augments Augments to add to.
2604 *
2605 * @return LY_ERR values.
2606 */
2607static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002608lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002609 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002610{
2611 struct lysp_node_augment *aug;
2612
2613 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2614
2615 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2616
2617 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2618 aug->nodetype = LYS_AUGMENT;
2619 aug->parent = parent;
2620
2621 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2622 switch (child->kw) {
2623 case LY_STMT_DESCRIPTION:
2624 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2625 break;
2626 case LY_STMT_IF_FEATURE:
2627 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2628 break;
2629 case LY_STMT_REFERENCE:
2630 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2631 break;
2632 case LY_STMT_STATUS:
2633 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2634 break;
2635 case LY_STMT_WHEN:
2636 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2637 break;
2638
2639 case LY_STMT_ANYDATA:
2640 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2641 /* fall through */
2642 case LY_STMT_ANYXML:
2643 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2644 break;
2645 case LY_STMT_CASE:
2646 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2647 break;
2648 case LY_STMT_CHOICE:
2649 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2650 break;
2651 case LY_STMT_CONTAINER:
2652 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2653 break;
2654 case LY_STMT_LEAF:
2655 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2656 break;
2657 case LY_STMT_LEAF_LIST:
2658 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2659 break;
2660 case LY_STMT_LIST:
2661 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2662 break;
2663 case LY_STMT_USES:
2664 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2665 break;
2666
2667 case LY_STMT_ACTION:
2668 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2669 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2670 break;
2671 case LY_STMT_NOTIFICATION:
2672 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2673 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2674 break;
2675 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002676 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002677 break;
2678 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002679 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002680 return LY_EVALID;
2681 }
2682 }
2683
2684 return LY_SUCCESS;
2685}
2686
2687/**
2688 * @brief Parse the uses statement.
2689 *
2690 * @param[in] ctx parser context.
2691 * @param[in] stmt Source statement data from the parsed extension instance.
2692 * @param[in] parent Parent node to connect to (not into).
2693 * @param[in,out] siblings Siblings to add to.
2694 *
2695 * @return LY_ERR values.
2696 */
2697static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002698lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002699 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002700{
2701 struct lysp_node_uses *uses;
2702
2703 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2704
2705 /* create uses structure */
2706 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2707
2708 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2709 uses->nodetype = LYS_USES;
2710 uses->parent = parent;
2711
2712 /* parse substatements */
2713 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2714 switch (child->kw) {
2715 case LY_STMT_DESCRIPTION:
2716 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2717 break;
2718 case LY_STMT_IF_FEATURE:
2719 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2720 break;
2721 case LY_STMT_REFERENCE:
2722 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2723 break;
2724 case LY_STMT_STATUS:
2725 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2726 break;
2727 case LY_STMT_WHEN:
2728 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2729 break;
2730
2731 case LY_STMT_REFINE:
2732 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2733 break;
2734 case LY_STMT_AUGMENT:
2735 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2736 break;
2737 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002738 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002739 break;
2740 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002741 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002742 return LY_EVALID;
2743 }
2744 }
2745
2746 return LY_SUCCESS;
2747}
2748
2749/**
2750 * @brief Parse the case statement.
2751 *
2752 * @param[in] ctx parser context.
2753 * @param[in] stmt Source statement data from the parsed extension instance.
2754 * @param[in] parent Parent node to connect to (not into).
2755 * @param[in,out] siblings Siblings to add to.
2756 *
2757 * @return LY_ERR values.
2758 */
2759static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002760lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002761 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002762{
2763 struct lysp_node_case *cas;
2764
2765 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2766
2767 /* create new case structure */
2768 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2769
2770 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2771 cas->nodetype = LYS_CASE;
2772 cas->parent = parent;
2773
2774 /* parse substatements */
2775 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2776 switch (child->kw) {
2777 case LY_STMT_DESCRIPTION:
2778 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2779 break;
2780 case LY_STMT_IF_FEATURE:
2781 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2782 break;
2783 case LY_STMT_REFERENCE:
2784 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2785 break;
2786 case LY_STMT_STATUS:
2787 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2788 break;
2789 case LY_STMT_WHEN:
2790 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2791 break;
2792
2793 case LY_STMT_ANYDATA:
2794 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2795 /* fall through */
2796 case LY_STMT_ANYXML:
2797 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2798 break;
2799 case LY_STMT_CHOICE:
2800 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2801 break;
2802 case LY_STMT_CONTAINER:
2803 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2804 break;
2805 case LY_STMT_LEAF:
2806 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2807 break;
2808 case LY_STMT_LEAF_LIST:
2809 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2810 break;
2811 case LY_STMT_LIST:
2812 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2813 break;
2814 case LY_STMT_USES:
2815 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2816 break;
2817 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002818 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002819 break;
2820 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002821 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002822 return LY_EVALID;
2823 }
2824 }
2825 return LY_SUCCESS;
2826}
2827
2828/**
2829 * @brief Parse the choice statement.
2830 *
2831 * @param[in] ctx parser context.
2832 * @param[in] stmt Source statement data from the parsed extension instance.
2833 * @param[in] parent Parent node to connect to (not into).
2834 * @param[in,out] siblings Siblings to add to.
2835 *
2836 * @return LY_ERR values.
2837 */
2838static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002839lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002840 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002841{
2842 struct lysp_node_choice *choice;
2843
2844 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2845
2846 /* create new choice structure */
2847 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2848
2849 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2850 choice->nodetype = LYS_CHOICE;
2851 choice->parent = parent;
2852
2853 /* parse substatements */
2854 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2855 switch (child->kw) {
2856 case LY_STMT_CONFIG:
2857 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2858 break;
2859 case LY_STMT_DESCRIPTION:
2860 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2861 break;
2862 case LY_STMT_IF_FEATURE:
2863 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2864 break;
2865 case LY_STMT_MANDATORY:
2866 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2867 break;
2868 case LY_STMT_REFERENCE:
2869 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2870 break;
2871 case LY_STMT_STATUS:
2872 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2873 break;
2874 case LY_STMT_WHEN:
2875 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2876 break;
2877 case LY_STMT_DEFAULT:
2878 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 +01002879 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002880 break;
2881 case LY_STMT_ANYDATA:
2882 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2883 /* fall through */
2884 case LY_STMT_ANYXML:
2885 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2886 break;
2887 case LY_STMT_CASE:
2888 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2889 break;
2890 case LY_STMT_CHOICE:
2891 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2892 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2893 break;
2894 case LY_STMT_CONTAINER:
2895 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2896 break;
2897 case LY_STMT_LEAF:
2898 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2899 break;
2900 case LY_STMT_LEAF_LIST:
2901 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2902 break;
2903 case LY_STMT_LIST:
2904 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2905 break;
2906 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002907 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002908 break;
2909 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002910 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002911 return LY_EVALID;
2912 }
2913 }
2914 return LY_SUCCESS;
2915}
2916
2917/**
2918 * @brief Parse the container statement.
2919 *
2920 * @param[in] ctx parser context.
2921 * @param[in] stmt Source statement data from the parsed extension instance.
2922 * @param[in] parent Parent node to connect to (not into).
2923 * @param[in,out] siblings Siblings to add to.
2924 *
2925 * @return LY_ERR values.
2926 */
2927static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002928lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002929 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002930{
2931 struct lysp_node_container *cont;
2932
2933 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2934
2935 /* create new container structure */
2936 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2937
2938 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2939 cont->nodetype = LYS_CONTAINER;
2940 cont->parent = parent;
2941
2942 /* parse substatements */
2943 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2944 switch (child->kw) {
2945 case LY_STMT_CONFIG:
2946 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
2947 break;
2948 case LY_STMT_DESCRIPTION:
2949 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
2950 break;
2951 case LY_STMT_IF_FEATURE:
2952 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
2953 break;
2954 case LY_STMT_REFERENCE:
2955 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
2956 break;
2957 case LY_STMT_STATUS:
2958 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
2959 break;
2960 case LY_STMT_WHEN:
2961 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
2962 break;
2963 case LY_STMT_PRESENCE:
2964 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
2965 break;
2966 case LY_STMT_ANYDATA:
2967 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
2968 /* fall through */
2969 case LY_STMT_ANYXML:
2970 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
2971 break;
2972 case LY_STMT_CHOICE:
2973 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
2974 break;
2975 case LY_STMT_CONTAINER:
2976 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
2977 break;
2978 case LY_STMT_LEAF:
2979 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
2980 break;
2981 case LY_STMT_LEAF_LIST:
2982 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
2983 break;
2984 case LY_STMT_LIST:
2985 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
2986 break;
2987 case LY_STMT_USES:
2988 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
2989 break;
2990
2991 case LY_STMT_TYPEDEF:
2992 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
2993 break;
2994 case LY_STMT_MUST:
2995 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
2996 break;
2997 case LY_STMT_ACTION:
2998 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
2999 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
3000 break;
3001 case LY_STMT_GROUPING:
3002 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3003 break;
3004 case LY_STMT_NOTIFICATION:
3005 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3006 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3007 break;
3008 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003009 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003010 break;
3011 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003012 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003013 return LY_EVALID;
3014 }
3015 }
3016
3017 return LY_SUCCESS;
3018}
3019
3020/**
3021 * @brief Parse the list statement.
3022 *
3023 * @param[in] ctx parser context.
3024 * @param[in] stmt Source statement data from the parsed extension instance.
3025 * @param[in] parent Parent node to connect to (not into).
3026 * @param[in,out] siblings Siblings to add to.
3027 *
3028 * @return LY_ERR values.
3029 */
3030static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003031lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003032 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003033{
3034 struct lysp_node_list *list;
3035
3036 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3037
3038 /* create new list structure */
3039 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3040
3041 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3042 list->nodetype = LYS_LIST;
3043 list->parent = parent;
3044
3045 /* parse substatements */
3046 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3047 switch (child->kw) {
3048 case LY_STMT_CONFIG:
3049 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3050 break;
3051 case LY_STMT_DESCRIPTION:
3052 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3053 break;
3054 case LY_STMT_IF_FEATURE:
3055 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3056 break;
3057 case LY_STMT_REFERENCE:
3058 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3059 break;
3060 case LY_STMT_STATUS:
3061 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3062 break;
3063 case LY_STMT_WHEN:
3064 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3065 break;
3066 case LY_STMT_KEY:
3067 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3068 break;
3069 case LY_STMT_MAX_ELEMENTS:
3070 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3071 break;
3072 case LY_STMT_MIN_ELEMENTS:
3073 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3074 break;
3075 case LY_STMT_ORDERED_BY:
3076 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3077 break;
3078 case LY_STMT_UNIQUE:
3079 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3080 break;
3081
3082 case LY_STMT_ANYDATA:
3083 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3084 /* fall through */
3085 case LY_STMT_ANYXML:
3086 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3087 break;
3088 case LY_STMT_CHOICE:
3089 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3090 break;
3091 case LY_STMT_CONTAINER:
3092 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3093 break;
3094 case LY_STMT_LEAF:
3095 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3096 break;
3097 case LY_STMT_LEAF_LIST:
3098 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3099 break;
3100 case LY_STMT_LIST:
3101 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3102 break;
3103 case LY_STMT_USES:
3104 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3105 break;
3106
3107 case LY_STMT_TYPEDEF:
3108 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3109 break;
3110 case LY_STMT_MUST:
3111 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3112 break;
3113 case LY_STMT_ACTION:
3114 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3115 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3116 break;
3117 case LY_STMT_GROUPING:
3118 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3119 break;
3120 case LY_STMT_NOTIFICATION:
3121 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3122 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3123 break;
3124 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003125 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003126 break;
3127 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003128 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003129 return LY_EVALID;
3130 }
3131 }
3132
3133 return LY_SUCCESS;
3134}
3135
Michal Vasko193dacd2022-10-13 08:43:05 +02003136/**
3137 * @brief Parse generic statement structure into a specific parsed-schema structure.
3138 *
3139 * @param[in] pctx Parse context of the @p stmt being processed.
3140 * @param[in] stmt Generic statement structure to process.
3141 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3142 * @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.
3143 * @return LY_ERR value.
3144 */
3145static LY_ERR
3146lysp_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 +02003147{
Radek Krejciad5963b2019-09-06 16:03:05 +02003148 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003149 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003150
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003151 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003152 case LY_STMT_NOTIFICATION:
3153 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3154 break;
3155 case LY_STMT_INPUT:
3156 case LY_STMT_OUTPUT: {
3157 struct lysp_node_action_inout *inout;
3158
3159 *result = inout = calloc(1, sizeof *inout);
3160 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3161 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3162 break;
3163 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003164 case LY_STMT_ACTION:
3165 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003166 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003167 break;
3168 case LY_STMT_ANYDATA:
3169 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003170 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003171 break;
3172 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003173 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003174 break;
3175 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003176 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003177 break;
3178 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003179 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003180 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003181 case LY_STMT_CONTAINER:
3182 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003183 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003184 case LY_STMT_GROUPING:
3185 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3186 break;
3187 case LY_STMT_LEAF:
3188 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3189 break;
3190 case LY_STMT_LEAF_LIST:
3191 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3192 break;
3193 case LY_STMT_LIST:
3194 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3195 break;
3196 case LY_STMT_USES:
3197 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3198 break;
3199 case LY_STMT_BASE:
3200 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3201 break;
3202 case LY_STMT_ARGUMENT:
3203 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003204 case LY_STMT_CONTACT:
3205 case LY_STMT_DESCRIPTION:
3206 case LY_STMT_ERROR_APP_TAG:
3207 case LY_STMT_ERROR_MESSAGE:
3208 case LY_STMT_KEY:
3209 case LY_STMT_NAMESPACE:
3210 case LY_STMT_ORGANIZATION:
3211 case LY_STMT_PRESENCE:
3212 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003213 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003214 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003215 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003216 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003217 case LY_STMT_BIT:
3218 case LY_STMT_ENUM:
3219 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3220 break;
3221 case LY_STMT_CONFIG:
3222 assert(*result);
3223 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003224 break;
3225 case LY_STMT_DEFAULT:
3226 case LY_STMT_IF_FEATURE:
3227 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003228 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3229 break;
3230 case LY_STMT_DEVIATE:
3231 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3232 break;
3233 case LY_STMT_DEVIATION:
3234 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3235 break;
3236 case LY_STMT_EXTENSION:
3237 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003238 break;
3239 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003240 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3241 break;
3242 case LY_STMT_FEATURE:
3243 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003244 break;
3245 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003246 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003247 break;
3248 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003249 case LY_STMT_RANGE: {
3250 struct lysp_restr *restr;
3251
3252 *result = restr = calloc(1, sizeof *restr);
3253 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3254
3255 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003256 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003257 }
3258 case LY_STMT_MUST:
3259 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3260 break;
3261 case LY_STMT_IDENTITY:
3262 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3263 break;
3264 case LY_STMT_IMPORT:
3265 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3266 break;
3267 case LY_STMT_INCLUDE:
3268 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003269 break;
3270 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003271 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003272 break;
3273 case LY_STMT_MAX_ELEMENTS:
3274 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003275 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003276 break;
3277 case LY_STMT_MIN_ELEMENTS:
3278 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003279 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003280 break;
3281 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003282 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003283 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003284 case LY_STMT_MODULE: {
3285 struct lysp_module *mod;
3286
3287 *result = mod = calloc(1, sizeof *mod);
3288 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3289 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003290 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003291 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003292 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003293 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003294 break;
3295 case LY_STMT_PATH: {
3296 const char *str_path = NULL;
3297
Michal Vasko193dacd2022-10-13 08:43:05 +02003298 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3299 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003300 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003301 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003302 break;
3303 }
3304 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003305 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003306 break;
3307 case LY_STMT_POSITION:
3308 case LY_STMT_VALUE:
3309 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003310 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003311 break;
3312 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003313 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003314 break;
3315 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003316 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003317 break;
3318 case LY_STMT_REQUIRE_INSTANCE:
3319 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003320 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3321 break;
3322 case LY_STMT_REVISION:
3323 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003324 break;
Michal Vasko69730152020-10-09 16:30:07 +02003325 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003326 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003327 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003328 case LY_STMT_SUBMODULE: {
3329 struct lysp_submodule *submod;
3330
3331 *result = submod = calloc(1, sizeof *submod);
3332 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3333 ret = lysp_stmt_submodule(pctx, stmt, submod);
3334 break;
3335 }
Radek Krejci335332a2019-09-05 13:03:35 +02003336 case LY_STMT_TYPE: {
3337 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003338
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003339 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003340 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3341 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003342 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003343 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003344 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003345 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003346 break;
3347 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003348 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3349 break;
3350 case LY_STMT_YANG_VERSION:
3351 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3352 break;
3353 case LY_STMT_YIN_ELEMENT:
3354 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003355 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003356 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003357 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003358 return LY_EINT;
3359 }
3360
Radek Krejciad5963b2019-09-06 16:03:05 +02003361 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003362}
Michal Vasko59892dd2022-05-13 11:02:30 +02003363
Michal Vasko193dacd2022-10-13 08:43:05 +02003364LY_ERR
3365lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003366{
Michal Vasko193dacd2022-10-13 08:43:05 +02003367 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003368
Michal Vasko193dacd2022-10-13 08:43:05 +02003369 if (!substmt->storage) {
3370 /* nothing to parse, ignored */
3371 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003372 }
3373
Michal Vasko193dacd2022-10-13 08:43:05 +02003374 switch (stmt->kw) {
3375 case LY_STMT_NOTIFICATION:
3376 case LY_STMT_INPUT:
3377 case LY_STMT_OUTPUT:
3378 case LY_STMT_ACTION:
3379 case LY_STMT_RPC:
3380 case LY_STMT_ANYDATA:
3381 case LY_STMT_ANYXML:
3382 case LY_STMT_AUGMENT:
3383 case LY_STMT_CASE:
3384 case LY_STMT_CHOICE:
3385 case LY_STMT_CONTAINER:
3386 case LY_STMT_GROUPING:
3387 case LY_STMT_LEAF:
3388 case LY_STMT_LEAF_LIST:
3389 case LY_STMT_LIST:
3390 case LY_STMT_USES: {
3391 struct lysp_node **pnodes_p, *pnode = NULL;
3392
3393 /* parse the node */
3394 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3395
3396 /* usually is a linked-list of all the parsed schema nodes */
3397 pnodes_p = substmt->storage;
3398 while (*pnodes_p) {
3399 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003400 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003401 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003402
3403 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003404 }
3405 case LY_STMT_BASE:
3406 case LY_STMT_BIT:
3407 case LY_STMT_DEFAULT:
3408 case LY_STMT_DEVIATE:
3409 case LY_STMT_DEVIATION:
3410 case LY_STMT_ENUM:
3411 case LY_STMT_EXTENSION:
3412 case LY_STMT_EXTENSION_INSTANCE:
3413 case LY_STMT_FEATURE:
3414 case LY_STMT_IDENTITY:
3415 case LY_STMT_IF_FEATURE:
3416 case LY_STMT_IMPORT:
3417 case LY_STMT_INCLUDE:
3418 case LY_STMT_MUST:
3419 case LY_STMT_PATTERN:
3420 case LY_STMT_REFINE:
3421 case LY_STMT_REVISION:
3422 case LY_STMT_TYPEDEF:
3423 case LY_STMT_UNIQUE:
3424 /* parse, sized array */
3425 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003426 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003427
3428 case LY_STMT_ARGUMENT:
3429 case LY_STMT_BELONGS_TO:
3430 case LY_STMT_CONTACT:
3431 case LY_STMT_DESCRIPTION:
3432 case LY_STMT_ERROR_APP_TAG:
3433 case LY_STMT_ERROR_MESSAGE:
3434 case LY_STMT_FRACTION_DIGITS:
3435 case LY_STMT_KEY:
3436 case LY_STMT_LENGTH:
3437 case LY_STMT_MANDATORY:
3438 case LY_STMT_MAX_ELEMENTS:
3439 case LY_STMT_MIN_ELEMENTS:
3440 case LY_STMT_MODIFIER:
3441 case LY_STMT_MODULE:
3442 case LY_STMT_NAMESPACE:
3443 case LY_STMT_ORGANIZATION:
3444 case LY_STMT_PATH:
3445 case LY_STMT_POSITION:
3446 case LY_STMT_PREFIX:
3447 case LY_STMT_PRESENCE:
3448 case LY_STMT_RANGE:
3449 case LY_STMT_REFERENCE:
3450 case LY_STMT_REQUIRE_INSTANCE:
3451 case LY_STMT_REVISION_DATE:
3452 case LY_STMT_SUBMODULE:
3453 case LY_STMT_TYPE:
3454 case LY_STMT_UNITS:
3455 case LY_STMT_VALUE:
3456 case LY_STMT_WHEN:
3457 case LY_STMT_YANG_VERSION:
3458 case LY_STMT_YIN_ELEMENT:
3459 /* single item */
3460 if (*(void **)substmt->storage) {
3461 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3462 rc = LY_EVALID;
3463 goto cleanup;
3464 }
3465
3466 /* parse */
3467 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003468 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003469
3470 case LY_STMT_CONFIG:
3471 /* single item */
3472 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3473 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3474 rc = LY_EVALID;
3475 goto cleanup;
3476 }
3477
3478 /* parse */
3479 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3480 break;
3481
3482 case LY_STMT_ORDERED_BY:
3483 /* single item */
3484 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3485 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3486 rc = LY_EVALID;
3487 goto cleanup;
3488 }
3489
3490 /* parse */
3491 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3492 break;
3493
3494 case LY_STMT_STATUS:
3495 /* single item */
3496 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3497 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3498 rc = LY_EVALID;
3499 goto cleanup;
3500 }
3501
3502 /* parse */
3503 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3504 break;
3505
Michal Vasko59892dd2022-05-13 11:02:30 +02003506 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003507 LOGINT(PARSER_CTX(pctx));
3508 rc = LY_EINT;
3509 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003510 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003511
3512cleanup:
3513 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003514}