blob: cd323002908ce67432fa984ff4e91ca8fd6b6559 [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;
269 } else {
270 *meta = (*meta)->next;
271 }
272 lyd_free_meta_single(meta2);
273 break;
274 }
275
276 prev_meta = meta2;
277 }
278
279 if (ext) {
280 /* parsed for an extension */
281 node->flags |= LYD_EXT;
282
283 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
284 /* rememeber for validation */
285 ext_val = malloc(sizeof *ext_val);
286 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
287 ext_val->ext = ext;
288 ext_val->sibling = node;
289 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
290 }
291 }
292
293 return LY_SUCCESS;
294}
295
Michal Vasko193dacd2022-10-13 08:43:05 +0200296void
297lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
298{
299 char path[PATH_MAX];
300
301#ifndef __APPLE__
302 char proc_path[32];
303 int len;
304#endif
305
306 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
307 if (*filepath) {
308 /* filepath already set */
309 return;
310 }
311
312 switch (in->type) {
313 case LY_IN_FILEPATH:
314 if (realpath(in->method.fpath.filepath, path) != NULL) {
315 lydict_insert(ctx, path, 0, filepath);
316 } else {
317 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
318 }
319
320 break;
321 case LY_IN_FD:
322#ifdef __APPLE__
323 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
324 lydict_insert(ctx, path, 0, filepath);
325 }
326#elif defined _WIN32
327 HANDLE h = _get_osfhandle(in->method.fd);
328 FILE_NAME_INFO info;
329 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
330 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
331 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
332 lydict_insert(ctx, buf, len, filepath);
333 }
334#else
335 /* get URI if there is /proc */
336 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
337 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
338 lydict_insert(ctx, path, len, filepath);
339 }
340#endif
341 break;
342 case LY_IN_MEMORY:
343 case LY_IN_FILE:
344 /* nothing to do */
345 break;
346 default:
347 LOGINT(ctx);
348 break;
349 }
350}
351
Michal Vaskod0625d72022-10-06 15:02:50 +0200352static 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 +0100353 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200354static 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 +0100355 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200356static 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 +0100357 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200358static 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 +0100359 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200360static 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 +0100361 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200362static 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 +0100363 struct lysp_node **siblings);
364
Radek Krejci335332a2019-09-05 13:03:35 +0200365static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200366lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200367{
Radek Krejci857189e2020-09-01 13:26:36 +0200368 uint8_t prefix = 0;
369 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200370 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200371 size_t utf8_char_len;
372
373 while (*val) {
374 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200375 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200376
377 switch (val_type) {
378 case Y_IDENTIF_ARG:
379 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
380 break;
381 case Y_PREF_IDENTIF_ARG:
382 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
383 break;
384 case Y_STR_ARG:
385 case Y_MAYBE_STR_ARG:
386 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
387 break;
388 }
389 first = 0;
390 }
391
392 return LY_SUCCESS;
393}
394
395/**
396 * @brief Parse extension instance.
397 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100398 * @param[in] ctx parser context.
399 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100400 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200401 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
402 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200403 * @return LY_ERR values.
404 */
405static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200406lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200407 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200408{
409 struct lysp_ext_instance *e;
410
Michal Vaskob36053d2020-03-26 15:49:30 +0100411 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200412
413 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200414 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100415 e->parent_stmt = insubstmt;
416 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200417 e->parsed = NULL;
Radek Krejci335332a2019-09-05 13:03:35 +0200418 /* TODO (duplicate) e->child = stmt->child; */
419
420 /* get optional argument */
421 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200422 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200423 }
424
425 return LY_SUCCESS;
426}
427
428/**
429 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
430 * description, etc...
431 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100432 * @param[in] ctx parser context.
433 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200434 * @param[in] substmt_index Index of this substatement.
435 * @param[in,out] value Place to store the parsed value.
436 * @param[in] arg Type of the YANG keyword argument (of the value).
437 * @param[in,out] exts Extension instances to add to.
438 *
439 * @return LY_ERR values.
440 */
441static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200442lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
443 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200444{
Radek Krejci335332a2019-09-05 13:03:35 +0200445 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200446 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200447 return LY_EVALID;
448 }
449
450 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200451 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200452
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100453 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
454 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200455 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100456 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200457 break;
458 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200459 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200460 return LY_EVALID;
461 }
462 }
463 return LY_SUCCESS;
464}
465
466/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200467 * @brief Parse a qname that can have more instances such as if-feature.
468 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100469 * @param[in] ctx parser context.
470 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200471 * @param[in,out] qnames Parsed qnames to add to.
472 * @param[in] arg Type of the expected argument.
473 * @param[in,out] exts Extension instances to add to.
474 *
475 * @return LY_ERR values.
476 */
477static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200478lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
479 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200480{
481 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200482
483 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
484
485 /* allocate new pointer */
486 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
487 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100488 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200489
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100490 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
491 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200492 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100493 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200494 break;
495 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200496 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200497 return LY_EVALID;
498 }
499 }
500 return LY_SUCCESS;
501}
502
503/**
Radek Krejci335332a2019-09-05 13:03:35 +0200504 * @brief Parse a generic text field that can have more instances such as base.
505 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100506 * @param[in] ctx parser context.
507 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200508 * @param[in,out] texts Parsed values to add to.
509 * @param[in] arg Type of the expected argument.
510 * @param[in,out] exts Extension instances to add to.
511 *
512 * @return LY_ERR values.
513 */
514static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200515lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
516 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200517{
518 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200519
520 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
521
522 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100523 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200524 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200525
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100526 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
527 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200528 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100529 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200530 break;
531 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200532 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200533 return LY_EVALID;
534 }
535 }
536 return LY_SUCCESS;
537}
538
539/**
540 * @brief Parse the status statement.
541 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100542 * @param[in] ctx parser context.
543 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200544 * @param[in,out] flags Flags to add to.
545 * @param[in,out] exts Extension instances to add to.
546 *
547 * @return LY_ERR values.
548 */
549static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200550lysp_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 +0200551{
552 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200553
554 if (*flags & LYS_STATUS_MASK) {
555 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
556 return LY_EVALID;
557 }
558
559 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
560 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100561 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200562 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100563 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200564 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100565 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200566 *flags |= LYS_STATUS_OBSLT;
567 } else {
568 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
569 return LY_EVALID;
570 }
571
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100572 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
573 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200574 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100575 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200576 break;
577 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200578 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200579 return LY_EVALID;
580 }
581 }
582 return LY_SUCCESS;
583}
584
585/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100586 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200587 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100588 * @param[in] ctx parser context.
589 * @param[in] stmt Source statement data from the parsed extension instance.
590 * @param[in,out] when_p When pointer to parse to.
591 *
592 * @return LY_ERR values.
593 */
594static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200595lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100596{
597 LY_ERR ret = LY_SUCCESS;
598 struct lysp_when *when;
599
600 if (*when_p) {
601 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
602 return LY_EVALID;
603 }
604
605 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
606
607 when = calloc(1, sizeof *when);
608 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
609 *when_p = when;
610
611 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
612
613 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
614 switch (child->kw) {
615 case LY_STMT_DESCRIPTION:
616 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
617 break;
618 case LY_STMT_REFERENCE:
619 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
620 break;
621 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100622 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100623 break;
624 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200625 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100626 return LY_EVALID;
627 }
628 }
629 return ret;
630}
631
632/**
633 * @brief Parse the config statement.
634 *
635 * @param[in] ctx parser context.
636 * @param[in] stmt Source statement data from the parsed extension instance.
637 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200638 * @param[in,out] exts Extension instances to add to.
639 *
640 * @return LY_ERR values.
641 */
642static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200643lysp_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 +0200644{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100645 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200646
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100647 if (*flags & LYS_CONFIG_MASK) {
648 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
649 return LY_EVALID;
650 }
651
652 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
653 arg_len = strlen(stmt->arg);
654 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
655 *flags |= LYS_CONFIG_W;
656 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
657 *flags |= LYS_CONFIG_R;
658 } else {
659 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
660 return LY_EVALID;
661 }
662
663 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
664 switch (child->kw) {
665 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100666 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100667 break;
668 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200669 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100670 return LY_EVALID;
671 }
672 }
673
674 return LY_SUCCESS;
675}
676
677/**
678 * @brief Parse the mandatory statement.
679 *
680 * @param[in] ctx parser context.
681 * @param[in] stmt Source statement data from the parsed extension instance.
682 * @param[in,out] flags Flags to add to.
683 * @param[in,out] exts Extension instances to add to.
684 *
685 * @return LY_ERR values.
686 */
687static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200688lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200689 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100690{
691 size_t arg_len;
692
693 if (*flags & LYS_MAND_MASK) {
694 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
695 return LY_EVALID;
696 }
697
698 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
699 arg_len = strlen(stmt->arg);
700 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
701 *flags |= LYS_MAND_TRUE;
702 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
703 *flags |= LYS_MAND_FALSE;
704 } else {
705 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
706 return LY_EVALID;
707 }
708
709 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
710 switch (child->kw) {
711 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100712 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100713 break;
714 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200715 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100716 return LY_EVALID;
717 }
718 }
719
720 return LY_SUCCESS;
721}
722
723/**
724 * @brief Parse a restriction such as range or length.
725 *
726 * @param[in] ctx parser context.
727 * @param[in] stmt Source statement data from the parsed extension instance.
728 * @param[in,out] exts Extension instances to add to.
729 *
730 * @return LY_ERR values.
731 */
732static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200733lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100734{
Radek Krejci335332a2019-09-05 13:03:35 +0200735 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200736 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100737 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200738
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100739 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
740 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200741 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100742 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200743 break;
744 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100745 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200746 break;
747 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100748 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200749 break;
750 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100751 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200752 break;
753 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100754 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200755 break;
756 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200757 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200758 return LY_EVALID;
759 }
760 }
761 return LY_SUCCESS;
762}
763
764/**
765 * @brief Parse a restriction that can have more instances such as must.
766 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100767 * @param[in] ctx parser context.
768 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200769 * @param[in,out] restrs Restrictions to add to.
770 *
771 * @return LY_ERR values.
772 */
773static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200774lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200775{
776 struct lysp_restr *restr;
777
Michal Vaskob36053d2020-03-26 15:49:30 +0100778 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100779 return lysp_stmt_restr(ctx, stmt, restr);
780}
781
782/**
783 * @brief Parse the anydata or anyxml statement.
784 *
785 * @param[in] ctx parser context.
786 * @param[in] stmt Source statement data from the parsed extension instance.
787 * @param[in,out] siblings Siblings to add to.
788 *
789 * @return LY_ERR values.
790 */
791static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200792lysp_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 +0100793{
794 struct lysp_node_anydata *any;
795
796 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
797
798 /* create new structure and insert into siblings */
799 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
800
801 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
802 any->parent = parent;
803
804 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
805
806 /* parse substatements */
807 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
808 switch (child->kw) {
809 case LY_STMT_CONFIG:
810 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
811 break;
812 case LY_STMT_DESCRIPTION:
813 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
814 break;
815 case LY_STMT_IF_FEATURE:
816 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
817 break;
818 case LY_STMT_MANDATORY:
819 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
820 break;
821 case LY_STMT_MUST:
822 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
823 break;
824 case LY_STMT_REFERENCE:
825 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
826 break;
827 case LY_STMT_STATUS:
828 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
829 break;
830 case LY_STMT_WHEN:
831 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
832 break;
833 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100834 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100835 break;
836 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200837 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
838 (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 +0100839 return LY_EVALID;
840 }
841 }
842
843 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200844}
845
846/**
847 * @brief Parse the value or position statement. Substatement of type enum statement.
848 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100849 * @param[in] ctx parser context.
850 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200851 * @param[in,out] value Value to write to.
852 * @param[in,out] flags Flags to write to.
853 * @param[in,out] exts Extension instances to add to.
854 *
855 * @return LY_ERR values.
856 */
857static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200858lysp_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 +0200859 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200860{
861 size_t arg_len;
862 char *ptr = NULL;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200863 long long int num = 0;
864 unsigned long long int unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200865
866 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200867 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200868 return LY_EVALID;
869 }
870 *flags |= LYS_SET_VALUE;
871
872 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
873
874 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100875 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
876 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200877 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200878 goto error;
879 }
880
881 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100882 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200883 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200884 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200885 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200886 goto error;
887 }
888 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200889 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200890 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200891 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200892 goto error;
893 }
894 }
895 /* we have not parsed the whole argument */
896 if ((size_t)(ptr - stmt->arg) != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200897 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200898 goto error;
899 }
900 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200901 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200902 goto error;
903 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100904 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200905 *value = num;
906 } else {
907 *value = unum;
908 }
909
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100910 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
911 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200912 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100913 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 +0200914 break;
915 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200916 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200917 return LY_EVALID;
918 }
919 }
920 return LY_SUCCESS;
921
922error:
923 return LY_EVALID;
924}
925
926/**
927 * @brief Parse the enum or bit statement. Substatement of type statement.
928 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100929 * @param[in] ctx parser context.
930 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200931 * @param[in,out] enums Enums or bits to add to.
932 *
933 * @return LY_ERR values.
934 */
935static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200936lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +0200937{
938 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200939
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100940 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 +0200941
Michal Vaskob36053d2020-03-26 15:49:30 +0100942 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200943
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100944 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +0200945 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
946 } /* else nothing specific for YANG_BIT */
947
Radek Krejci011e4aa2020-09-04 15:22:31 +0200948 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +0200949 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +0200950
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100951 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
952 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200953 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100954 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200955 break;
956 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +0200957 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100958 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200959 break;
960 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100961 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200962 break;
963 case LY_STMT_STATUS:
964 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
965 break;
966 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +0200967 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
968 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100969 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200970 break;
971 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +0200972 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
973 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100974 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200975 break;
976 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100977 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200978 break;
979 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200980 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200981 return LY_EVALID;
982 }
983 }
Michal Vasko193dacd2022-10-13 08:43:05 +0200984
Radek Krejci335332a2019-09-05 13:03:35 +0200985 return LY_SUCCESS;
986}
987
988/**
989 * @brief Parse the fraction-digits statement. Substatement of type statement.
990 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100991 * @param[in] ctx parser context.
992 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200993 * @param[in,out] fracdig Value to write to.
994 * @param[in,out] exts Extension instances to add to.
995 *
996 * @return LY_ERR values.
997 */
998static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200999lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001000 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001001{
1002 char *ptr;
1003 size_t arg_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001004 unsigned long long int num;
Radek Krejci335332a2019-09-05 13:03:35 +02001005
1006 if (*fracdig) {
1007 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1008 return LY_EVALID;
1009 }
1010
1011 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1012 arg_len = strlen(stmt->arg);
1013 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1014 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1015 return LY_EVALID;
1016 }
1017
1018 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001019 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001020 /* we have not parsed the whole argument */
1021 if ((size_t)(ptr - stmt->arg) != arg_len) {
1022 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1023 return LY_EVALID;
1024 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001025 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001026 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1027 return LY_EVALID;
1028 }
1029 *fracdig = num;
1030
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001031 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1032 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001033 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001034 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001035 break;
1036 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001037 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001038 return LY_EVALID;
1039 }
1040 }
1041 return LY_SUCCESS;
1042}
1043
1044/**
1045 * @brief Parse the require-instance statement. Substatement of type statement.
1046 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001047 * @param[in] ctx parser context.
1048 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001049 * @param[in,out] reqinst Value to write to.
1050 * @param[in,out] flags Flags to write to.
1051 * @param[in,out] exts Extension instances to add to.
1052 *
1053 * @return LY_ERR values.
1054 */
1055static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001056lysp_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 +02001057 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001058{
1059 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001060
1061 if (*flags & LYS_SET_REQINST) {
1062 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1063 return LY_EVALID;
1064 }
1065 *flags |= LYS_SET_REQINST;
1066
1067 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1068 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001069 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001070 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001071 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001072 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1073 return LY_EVALID;
1074 }
1075
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001076 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1077 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001078 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001079 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001080 break;
1081 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001082 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001083 return LY_EVALID;
1084 }
1085 }
1086 return LY_SUCCESS;
1087}
1088
1089/**
1090 * @brief Parse the modifier statement. Substatement of type pattern statement.
1091 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001092 * @param[in] ctx parser context.
1093 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001094 * @param[in,out] pat Value to write to.
1095 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001096 * @return LY_ERR values.
1097 */
1098static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001099lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001100 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001101{
1102 size_t arg_len;
1103 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001104
Radek Krejcif13b87b2020-12-01 22:02:17 +01001105 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001106 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1107 return LY_EVALID;
1108 }
1109
1110 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1111 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001112 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001113 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1114 return LY_EVALID;
1115 }
1116
1117 /* replace the value in the dictionary */
1118 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001119 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001120 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001121 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001122
Radek Krejcif13b87b2020-12-01 22:02:17 +01001123 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1124 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001125 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001126
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001127 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1128 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001129 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001130 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001131 break;
1132 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001133 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001134 return LY_EVALID;
1135 }
1136 }
1137 return LY_SUCCESS;
1138}
1139
1140/**
1141 * @brief Parse the pattern statement. Substatement of type statement.
1142 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001143 * @param[in] ctx parser context.
1144 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001145 * @param[in,out] patterns Restrictions to add to.
1146 *
1147 * @return LY_ERR values.
1148 */
1149static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001150lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001151{
1152 char *buf;
1153 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001154 struct lysp_restr *restr;
1155
1156 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001157 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001158 arg_len = strlen(stmt->arg);
1159
1160 /* add special meaning first byte */
1161 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001162 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001163 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001164 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001165 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001166 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001167 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001168
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001169 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1170 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001171 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001172 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001173 break;
1174 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001175 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001176 break;
1177 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001178 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001179 break;
1180 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001181 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001182 break;
1183 case LY_STMT_MODIFIER:
1184 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001185 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001186 break;
1187 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001188 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001189 break;
1190 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001191 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001192 return LY_EVALID;
1193 }
1194 }
1195 return LY_SUCCESS;
1196}
1197
1198/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001199 * @brief Parse the deviate statement. Substatement of deviation statement.
1200 *
1201 * @param[in] ctx parser context.
1202 * @param[in] stmt Source statement data from the parsed extension instance.
1203 * @param[in,out] devs Array of deviates to add to.
1204 * @param[in,out] exts Extension instances to add to.
1205 * @return LY_ERR values.
1206 */
1207static LY_ERR
1208lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1209{
1210 (void)stmt;
1211 (void)devs;
1212 (void)exts;
1213
1214 /* TODO */
1215 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1216 return LY_EINVAL;
1217}
1218
1219/**
1220 * @brief Parse the deviation statement.
1221 *
1222 * @param[in] ctx parser context.
1223 * @param[in] stmt Source statement data from the parsed extension instance.
1224 * @param[in,out] deviations Array of deviations to add to.
1225 * @return LY_ERR values.
1226 */
1227static LY_ERR
1228lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1229{
1230 struct lysp_deviation *dev;
1231
1232 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1233
1234 /* store nodeid */
1235 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1236 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1237
1238 /* parse substatements */
1239 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1240 switch (child->kw) {
1241 case LY_STMT_DESCRIPTION:
1242 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1243 break;
1244 case LY_STMT_DEVIATE:
1245 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1246 break;
1247 case LY_STMT_REFERENCE:
1248 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1249 break;
1250 case LY_STMT_EXTENSION_INSTANCE:
1251 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1252 break;
1253 default:
1254 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1255 return LY_EVALID;
1256 }
1257 }
1258
1259 return LY_SUCCESS;
1260}
1261
1262/**
1263 * @brief Parse the yang-version statement.
1264 *
1265 * @param[in] ctx parser context.
1266 * @param[in] stmt Source statement data from the parsed extension instance.
1267 * @param[out] version Version to write to.
1268 * @param[in,out] exts Extension instances to add to.
1269 * @return LY_ERR values.
1270 */
1271static LY_ERR
1272lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1273{
1274 if (*version) {
1275 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1276 return LY_EVALID;
1277 }
1278
1279 /* store flag */
1280 if (!strcmp(stmt->arg, "1")) {
1281 *version = LYS_VERSION_1_0;
1282 } else if (!strcmp(stmt->arg, "1.1")) {
1283 *version = LYS_VERSION_1_1;
1284 } else {
1285 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yang-version");
1286 return LY_EVALID;
1287 }
1288
1289 /* parse substatements */
1290 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1291 switch (child->kw) {
1292 case LY_STMT_EXTENSION_INSTANCE:
1293 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1294 break;
1295 default:
1296 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1297 return LY_EVALID;
1298 }
1299 }
1300
1301 return LY_SUCCESS;
1302}
1303
1304/**
1305 * @brief Parse the module statement.
1306 *
1307 * @param[in] ctx parser context.
1308 * @param[in] stmt Source statement data from the parsed extension instance.
1309 * @param[in,out] mod Module to fill.
1310 * @return LY_ERR values.
1311 */
1312static LY_ERR
1313lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1314{
1315 (void)stmt;
1316 (void)mod;
1317
1318 /* TODO */
1319 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1320 return LY_EINVAL;
1321}
1322
1323/**
1324 * @brief Parse the submodule statement.
1325 *
1326 * @param[in] ctx parser context.
1327 * @param[in] stmt Source statement data from the parsed extension instance.
1328 * @param[in,out] submod Module to fill.
1329 * @return LY_ERR values.
1330 */
1331static LY_ERR
1332lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1333{
1334 (void)stmt;
1335 (void)submod;
1336
1337 /* TODO */
1338 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1339 return LY_EINVAL;
1340}
1341
1342/**
1343 * @brief Parse the yin-element statement. Substatement of argument statement.
1344 *
1345 * @param[in] ctx parser context.
1346 * @param[in] stmt Source statement data from the parsed extension instance.
1347 * @param[in,out] flags Flags to write to.
1348 * @param[in,out] exts Extension instances to add to.
1349 * @return LY_ERR values.
1350 */
1351static LY_ERR
1352lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1353{
1354 if (*flags & LYS_YINELEM_MASK) {
1355 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1356 return LY_EVALID;
1357 }
1358
1359 /* store flag */
1360 if (!strcmp(stmt->arg, "true")) {
1361 *flags |= LYS_YINELEM_TRUE;
1362 } else if (!strcmp(stmt->arg, "false")) {
1363 *flags |= LYS_YINELEM_FALSE;
1364 } else {
1365 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yin-element");
1366 return LY_EVALID;
1367 }
1368
1369 /* parse substatements */
1370 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1371 switch (child->kw) {
1372 case LY_STMT_EXTENSION_INSTANCE:
1373 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1374 break;
1375 default:
1376 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1377 return LY_EVALID;
1378 }
1379 }
1380
1381 return LY_SUCCESS;
1382}
1383
1384/**
1385 * @brief Parse the argument statement. Substatement of extension statement.
1386 *
1387 * @param[in] ctx parser context.
1388 * @param[in] stmt Source statement data from the parsed extension instance.
1389 * @param[in,out] ex Extension to fill.
1390 * @return LY_ERR values.
1391 */
1392static LY_ERR
1393lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1394{
1395 if (ex->argname) {
1396 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1397 return LY_EVALID;
1398 }
1399
1400 /* store argument name */
1401 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1402 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1403
1404 /* parse substatements */
1405 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1406 switch (child->kw) {
1407 case LY_STMT_YIN_ELEMENT:
1408 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1409 break;
1410 case LY_STMT_EXTENSION_INSTANCE:
1411 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1412 break;
1413 default:
1414 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1415 return LY_EVALID;
1416 }
1417 }
1418
1419 return LY_SUCCESS;
1420}
1421
1422/**
1423 * @brief Parse the extension statement.
1424 *
1425 * @param[in] ctx parser context.
1426 * @param[in] stmt Source statement data from the parsed extension instance.
1427 * @param[in,out] extensions Array of extensions to add to.
1428 * @return LY_ERR values.
1429 */
1430static LY_ERR
1431lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1432{
1433 struct lysp_ext *ex;
1434
1435 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1436
1437 /* store name */
1438 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1439 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1440
1441 /* parse substatements */
1442 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1443 switch (child->kw) {
1444 case LY_STMT_DESCRIPTION:
1445 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1446 break;
1447 case LY_STMT_REFERENCE:
1448 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1449 break;
1450 case LY_STMT_STATUS:
1451 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1452 break;
1453 case LY_STMT_ARGUMENT:
1454 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1455 break;
1456 case LY_STMT_EXTENSION_INSTANCE:
1457 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1458 break;
1459 default:
1460 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1461 return LY_EVALID;
1462 }
1463 }
1464
1465 return LY_SUCCESS;
1466}
1467
1468/**
1469 * @brief Parse the feature statement.
1470 *
1471 * @param[in] ctx parser context.
1472 * @param[in] stmt Source statement data from the parsed extension instance.
1473 * @param[in,out] features Array of features to add to.
1474 * @return LY_ERR values.
1475 */
1476static LY_ERR
1477lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1478{
1479 struct lysp_feature *feat;
1480
1481 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1482
1483 /* store name */
1484 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1485 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1486
1487 /* parse substatements */
1488 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1489 switch (child->kw) {
1490 case LY_STMT_DESCRIPTION:
1491 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1492 break;
1493 case LY_STMT_IF_FEATURE:
1494 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1495 break;
1496 case LY_STMT_REFERENCE:
1497 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1498 break;
1499 case LY_STMT_STATUS:
1500 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1501 break;
1502 case LY_STMT_EXTENSION_INSTANCE:
1503 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1504 break;
1505 default:
1506 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1507 return LY_EVALID;
1508 }
1509 }
1510
1511 return LY_SUCCESS;
1512}
1513
1514/**
1515 * @brief Parse the identity statement.
1516 *
1517 * @param[in] ctx parser context.
1518 * @param[in] stmt Source statement data from the parsed extension instance.
1519 * @param[in,out] identities Array of identities to add to.
1520 * @return LY_ERR values.
1521 */
1522static LY_ERR
1523lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1524{
1525 struct lysp_ident *ident;
1526
1527 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1528
1529 /* store name */
1530 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1531 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1532
1533 /* parse substatements */
1534 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1535 switch (child->kw) {
1536 case LY_STMT_DESCRIPTION:
1537 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1538 break;
1539 case LY_STMT_IF_FEATURE:
1540 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1541 break;
1542 case LY_STMT_REFERENCE:
1543 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1544 break;
1545 case LY_STMT_STATUS:
1546 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1547 break;
1548 case LY_STMT_BASE:
1549 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1550 break;
1551 case LY_STMT_EXTENSION_INSTANCE:
1552 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1553 break;
1554 default:
1555 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1556 return LY_EVALID;
1557 }
1558 }
1559
1560 return LY_SUCCESS;
1561}
1562
1563/**
1564 * @brief Parse the import statement.
1565 *
1566 * @param[in] ctx parser context.
1567 * @param[in] stmt Source statement data from the parsed extension instance.
1568 * @param[in,out] imports Array of imports to add to.
1569 * @return LY_ERR values.
1570 */
1571static LY_ERR
1572lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1573{
1574 struct lysp_import *imp;
1575 const char *str = NULL;
1576
1577 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1578
1579 /* store name */
1580 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1581 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1582
1583 /* parse substatements */
1584 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1585 switch (child->kw) {
1586 case LY_STMT_PREFIX:
1587 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1588 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1589 break;
1590 case LY_STMT_DESCRIPTION:
1591 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1592 break;
1593 case LY_STMT_REFERENCE:
1594 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1595 break;
1596 case LY_STMT_REVISION_DATE:
1597 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1598 strcpy(imp->rev, str);
1599 lydict_remove(PARSER_CTX(ctx), str);
1600 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1601 break;
1602 case LY_STMT_EXTENSION_INSTANCE:
1603 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1604 break;
1605 default:
1606 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1607 return LY_EVALID;
1608 }
1609 }
1610
1611 return LY_SUCCESS;
1612}
1613
1614/**
1615 * @brief Parse the include statement.
1616 *
1617 * @param[in] ctx parser context.
1618 * @param[in] stmt Source statement data from the parsed extension instance.
1619 * @param[in,out] includes Array of identities to add to.
1620 * @return LY_ERR values.
1621 */
1622static LY_ERR
1623lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1624{
1625 struct lysp_include *inc;
1626 const char *str = NULL;
1627
1628 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1629
1630 /* store name */
1631 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1632 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1633
1634 /* parse substatements */
1635 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1636 switch (child->kw) {
1637 case LY_STMT_DESCRIPTION:
1638 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1639 break;
1640 case LY_STMT_REFERENCE:
1641 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1642 break;
1643 case LY_STMT_REVISION_DATE:
1644 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1645 strcpy(inc->rev, str);
1646 lydict_remove(PARSER_CTX(ctx), str);
1647 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1648 break;
1649 case LY_STMT_EXTENSION_INSTANCE:
1650 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1651 break;
1652 default:
1653 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1654 return LY_EVALID;
1655 }
1656 }
1657
1658 return LY_SUCCESS;
1659}
1660
1661/**
1662 * @brief Parse the revision statement.
1663 *
1664 * @param[in] ctx parser context.
1665 * @param[in] stmt Source statement data from the parsed extension instance.
1666 * @param[in,out] includes Array of identities to add to.
1667 * @return LY_ERR values.
1668 */
1669static LY_ERR
1670lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1671{
1672 struct lysp_revision *rev;
1673
1674 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1675
1676 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001677 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001678 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001679
1680 /* parse substatements */
1681 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1682 switch (child->kw) {
1683 case LY_STMT_DESCRIPTION:
1684 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1685 break;
1686 case LY_STMT_REFERENCE:
1687 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1688 break;
1689 case LY_STMT_EXTENSION_INSTANCE:
1690 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1691 break;
1692 default:
1693 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1694 return LY_EVALID;
1695 }
1696 }
1697
1698 return LY_SUCCESS;
1699}
1700
1701/**
Radek Krejci335332a2019-09-05 13:03:35 +02001702 * @brief Parse the type statement.
1703 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001704 * @param[in] ctx parser context.
1705 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001706 * @param[in,out] type Type to wrote to.
1707 *
1708 * @return LY_ERR values.
1709 */
1710static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001711lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001712{
1713 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001714 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001715 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001716
1717 if (type->name) {
1718 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1719 return LY_EVALID;
1720 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001721
1722 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001723 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001724 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001725
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001726 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1727 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001728 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001729 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001730 type->flags |= LYS_SET_BASE;
1731 break;
1732 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001733 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001734 type->flags |= LYS_SET_BIT;
1735 break;
1736 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001737 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001738 type->flags |= LYS_SET_ENUM;
1739 break;
1740 case LY_STMT_FRACTION_DIGITS:
1741 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1742 type->flags |= LYS_SET_FRDIGITS;
1743 break;
1744 case LY_STMT_LENGTH:
1745 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001746 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001747 return LY_EVALID;
1748 }
1749 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001750 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001751
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001752 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001753 type->flags |= LYS_SET_LENGTH;
1754 break;
1755 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001756 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001757 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001758 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001759 lydict_remove(PARSER_CTX(ctx), str_path);
1760 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001761 type->flags |= LYS_SET_PATH;
1762 break;
1763 case LY_STMT_PATTERN:
1764 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1765 type->flags |= LYS_SET_PATTERN;
1766 break;
1767 case LY_STMT_RANGE:
1768 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001769 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001770 return LY_EVALID;
1771 }
1772 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001773 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001774
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001775 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001776 type->flags |= LYS_SET_RANGE;
1777 break;
1778 case LY_STMT_REQUIRE_INSTANCE:
1779 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001780 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001781 break;
1782 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001783 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001784 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1785 type->flags |= LYS_SET_TYPE;
1786 break;
1787 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001788 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001789 break;
1790 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001791 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001792 return LY_EVALID;
1793 }
1794 }
1795 return LY_SUCCESS;
1796}
1797
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001798/**
1799 * @brief Parse the leaf statement.
1800 *
1801 * @param[in] ctx parser context.
1802 * @param[in] stmt Source statement data from the parsed extension instance.
1803 * @param[in] parent Parent node to connect to (not into).
1804 * @param[in,out] siblings Siblings to add to.
1805 *
1806 * @return LY_ERR values.
1807 */
1808static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001809lysp_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 +01001810{
1811 struct lysp_node_leaf *leaf;
1812
1813 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1814
1815 /* create new leaf structure */
1816 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1817 leaf->nodetype = LYS_LEAF;
1818 leaf->parent = parent;
1819
1820 /* get name */
1821 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1822
1823 /* parse substatements */
1824 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1825 switch (child->kw) {
1826 case LY_STMT_CONFIG:
1827 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1828 break;
1829 case LY_STMT_DEFAULT:
1830 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 +01001831 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001832 break;
1833 case LY_STMT_DESCRIPTION:
1834 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1835 break;
1836 case LY_STMT_IF_FEATURE:
1837 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1838 break;
1839 case LY_STMT_MANDATORY:
1840 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1841 break;
1842 case LY_STMT_MUST:
1843 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1844 break;
1845 case LY_STMT_REFERENCE:
1846 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1847 break;
1848 case LY_STMT_STATUS:
1849 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1850 break;
1851 case LY_STMT_TYPE:
1852 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1853 break;
1854 case LY_STMT_UNITS:
1855 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1856 break;
1857 case LY_STMT_WHEN:
1858 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1859 break;
1860 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001861 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001862 break;
1863 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001864 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001865 return LY_EVALID;
1866 }
1867 }
1868
1869 /* mandatory substatements */
1870 if (!leaf->type.name) {
1871 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1872 return LY_EVALID;
1873 }
1874
1875 return LY_SUCCESS;
1876}
1877
1878/**
1879 * @brief Parse the max-elements statement.
1880 *
1881 * @param[in] ctx parser context.
1882 * @param[in] stmt Source statement data from the parsed extension instance.
1883 * @param[in,out] max Value to write to.
1884 * @param[in,out] flags Flags to write to.
1885 * @param[in,out] exts Extension instances to add to.
1886 *
1887 * @return LY_ERR values.
1888 */
1889static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001890lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
1891 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001892{
1893 size_t arg_len;
1894 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001895 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001896
1897 if (*flags & LYS_SET_MAX) {
1898 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1899 return LY_EVALID;
1900 }
1901 *flags |= LYS_SET_MAX;
1902
1903 /* get value */
1904 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1905 arg_len = strlen(stmt->arg);
1906
1907 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1908 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1909 return LY_EVALID;
1910 }
1911
1912 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1913 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001914 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001915 /* we have not parsed the whole argument */
1916 if ((size_t)(ptr - stmt->arg) != arg_len) {
1917 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1918 return LY_EVALID;
1919 }
1920 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1921 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1922 return LY_EVALID;
1923 }
1924
1925 *max = num;
1926 } else {
1927 /* unbounded */
1928 *max = 0;
1929 }
1930
1931 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1932 switch (child->kw) {
1933 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001934 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001935 break;
1936 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001937 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001938 return LY_EVALID;
1939 }
1940 }
1941
1942 return LY_SUCCESS;
1943}
1944
1945/**
1946 * @brief Parse the min-elements statement.
1947 *
1948 * @param[in] ctx parser context.
1949 * @param[in] stmt Source statement data from the parsed extension instance.
1950 * @param[in,out] min Value to write to.
1951 * @param[in,out] flags Flags to write to.
1952 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001953 * @return LY_ERR values.
1954 */
1955static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001956lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
1957 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001958{
1959 size_t arg_len;
1960 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001961 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001962
1963 if (*flags & LYS_SET_MIN) {
1964 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
1965 return LY_EVALID;
1966 }
1967 *flags |= LYS_SET_MIN;
1968
1969 /* get value */
1970 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1971 arg_len = strlen(stmt->arg);
1972
1973 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
1974 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1975 return LY_EVALID;
1976 }
1977
1978 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001979 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001980 /* we have not parsed the whole argument */
1981 if ((size_t)(ptr - stmt->arg) != arg_len) {
1982 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1983 return LY_EVALID;
1984 }
1985 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1986 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
1987 return LY_EVALID;
1988 }
1989 *min = num;
1990
1991 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1992 switch (child->kw) {
1993 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001994 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001995 break;
1996 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001997 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001998 return LY_EVALID;
1999 }
2000 }
2001
2002 return LY_SUCCESS;
2003}
2004
2005/**
2006 * @brief Parse the ordered-by statement.
2007 *
2008 * @param[in] ctx parser context.
2009 * @param[in] stmt Source statement data from the parsed extension instance.
2010 * @param[in,out] flags Flags to write to.
2011 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002012 * @return LY_ERR values.
2013 */
2014static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002015lysp_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 +01002016{
2017 size_t arg_len;
2018
2019 if (*flags & LYS_ORDBY_MASK) {
2020 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2021 return LY_EVALID;
2022 }
2023
2024 /* get value */
2025 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2026 arg_len = strlen(stmt->arg);
2027 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2028 *flags |= LYS_MAND_TRUE;
2029 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2030 *flags |= LYS_MAND_FALSE;
2031 } else {
2032 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2033 return LY_EVALID;
2034 }
2035
2036 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2037 switch (child->kw) {
2038 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002039 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002040 break;
2041 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002042 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002043 return LY_EVALID;
2044 }
2045 }
2046
2047 return LY_SUCCESS;
2048}
2049
2050/**
2051 * @brief Parse the leaf-list statement.
2052 *
2053 * @param[in] ctx parser context.
2054 * @param[in] stmt Source statement data from the parsed extension instance.
2055 * @param[in] parent Parent node to connect to (not into).
2056 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002057 * @return LY_ERR values.
2058 */
2059static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002060lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002061 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002062{
2063 struct lysp_node_leaflist *llist;
2064
2065 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2066
2067 /* create new leaf-list structure */
2068 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2069 llist->nodetype = LYS_LEAFLIST;
2070 llist->parent = parent;
2071
2072 /* get name */
2073 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2074
2075 /* parse substatements */
2076 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2077 switch (child->kw) {
2078 case LY_STMT_CONFIG:
2079 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2080 break;
2081 case LY_STMT_DEFAULT:
2082 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2083 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2084 break;
2085 case LY_STMT_DESCRIPTION:
2086 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2087 break;
2088 case LY_STMT_IF_FEATURE:
2089 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2090 break;
2091 case LY_STMT_MAX_ELEMENTS:
2092 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2093 break;
2094 case LY_STMT_MIN_ELEMENTS:
2095 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2096 break;
2097 case LY_STMT_MUST:
2098 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2099 break;
2100 case LY_STMT_ORDERED_BY:
2101 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2102 break;
2103 case LY_STMT_REFERENCE:
2104 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2105 break;
2106 case LY_STMT_STATUS:
2107 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2108 break;
2109 case LY_STMT_TYPE:
2110 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2111 break;
2112 case LY_STMT_UNITS:
2113 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2114 break;
2115 case LY_STMT_WHEN:
2116 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2117 break;
2118 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002119 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002120 break;
2121 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002122 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002123 return LY_EVALID;
2124 }
2125 }
2126
2127 /* mandatory substatements */
2128 if (!llist->type.name) {
2129 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2130 return LY_EVALID;
2131 }
2132
2133 return LY_SUCCESS;
2134}
2135
2136/**
2137 * @brief Parse the refine statement.
2138 *
2139 * @param[in] ctx parser context.
2140 * @param[in] stmt Source statement data from the parsed extension instance.
2141 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002142 * @return LY_ERR values.
2143 */
2144static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002145lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002146{
2147 struct lysp_refine *rf;
2148
2149 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2150
2151 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2152
2153 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2154
2155 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2156 switch (child->kw) {
2157 case LY_STMT_CONFIG:
2158 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2159 break;
2160 case LY_STMT_DEFAULT:
2161 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2162 break;
2163 case LY_STMT_DESCRIPTION:
2164 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2165 break;
2166 case LY_STMT_IF_FEATURE:
2167 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2168 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2169 break;
2170 case LY_STMT_MAX_ELEMENTS:
2171 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2172 break;
2173 case LY_STMT_MIN_ELEMENTS:
2174 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2175 break;
2176 case LY_STMT_MUST:
2177 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2178 break;
2179 case LY_STMT_MANDATORY:
2180 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2181 break;
2182 case LY_STMT_REFERENCE:
2183 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2184 break;
2185 case LY_STMT_PRESENCE:
2186 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2187 break;
2188 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002189 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002190 break;
2191 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002192 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002193 return LY_EVALID;
2194 }
2195 }
2196
2197 return LY_SUCCESS;
2198}
2199
2200/**
2201 * @brief Parse the typedef statement.
2202 *
2203 * @param[in] ctx parser context.
2204 * @param[in] stmt Source statement data from the parsed extension instance.
2205 * @param[in] parent Parent node to connect to (not into).
2206 * @param[in,out] typedefs Typedefs to add to.
2207 *
2208 * @return LY_ERR values.
2209 */
2210static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002211lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002212 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002213{
2214 struct lysp_tpdf *tpdf;
2215
2216 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2217
2218 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2219
2220 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2221
2222 /* parse substatements */
2223 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2224 switch (child->kw) {
2225 case LY_STMT_DEFAULT:
2226 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 +01002227 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002228 break;
2229 case LY_STMT_DESCRIPTION:
2230 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2231 break;
2232 case LY_STMT_REFERENCE:
2233 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2234 break;
2235 case LY_STMT_STATUS:
2236 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2237 break;
2238 case LY_STMT_TYPE:
2239 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2240 break;
2241 case LY_STMT_UNITS:
2242 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2243 break;
2244 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002245 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002246 break;
2247 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002248 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002249 return LY_EVALID;
2250 }
2251 }
2252
2253 /* mandatory substatements */
2254 if (!tpdf->type.name) {
2255 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2256 return LY_EVALID;
2257 }
2258
2259 /* store data for collision check */
2260 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2261 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2262 }
2263
2264 return LY_SUCCESS;
2265}
2266
2267/**
2268 * @brief Parse the input or output statement.
2269 *
2270 * @param[in] ctx parser context.
2271 * @param[in] stmt Source statement data from the parsed extension instance.
2272 * @param[in] parent Parent node to connect to (not into).
2273 * @param[in,out] inout_p Input/output pointer to write to.
2274 *
2275 * @return LY_ERR values.
2276 */
2277static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002278lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002279 struct lysp_node_action_inout *inout_p)
2280{
2281 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002282 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002283 return LY_EVALID;
2284 }
2285
2286 /* initiate structure */
2287 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2288 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2289 inout_p->parent = parent;
2290
2291 /* parse substatements */
2292 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2293 switch (child->kw) {
2294 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002295 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002296 /* fall through */
2297 case LY_STMT_ANYXML:
2298 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2299 break;
2300 case LY_STMT_CHOICE:
2301 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2302 break;
2303 case LY_STMT_CONTAINER:
2304 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2305 break;
2306 case LY_STMT_LEAF:
2307 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2308 break;
2309 case LY_STMT_LEAF_LIST:
2310 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2311 break;
2312 case LY_STMT_LIST:
2313 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2314 break;
2315 case LY_STMT_USES:
2316 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2317 break;
2318 case LY_STMT_TYPEDEF:
2319 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2320 break;
2321 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002322 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002323 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2324 break;
2325 case LY_STMT_GROUPING:
2326 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2327 break;
2328 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002329 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002330 break;
2331 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002332 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002333 return LY_EVALID;
2334 }
2335 }
2336
2337 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002338 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002339 return LY_EVALID;
2340 }
2341
2342 return LY_SUCCESS;
2343}
2344
2345/**
2346 * @brief Parse the action statement.
2347 *
2348 * @param[in] ctx parser context.
2349 * @param[in] stmt Source statement data from the parsed extension instance.
2350 * @param[in] parent Parent node to connect to (not into).
2351 * @param[in,out] actions Actions to add to.
2352 *
2353 * @return LY_ERR values.
2354 */
2355static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002356lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002357 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002358{
2359 struct lysp_node_action *act;
2360
2361 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2362
2363 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2364
2365 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2366 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2367 act->parent = parent;
2368
2369 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2370 switch (child->kw) {
2371 case LY_STMT_DESCRIPTION:
2372 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2373 break;
2374 case LY_STMT_IF_FEATURE:
2375 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2376 break;
2377 case LY_STMT_REFERENCE:
2378 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2379 break;
2380 case LY_STMT_STATUS:
2381 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2382 break;
2383
2384 case LY_STMT_INPUT:
2385 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2386 break;
2387 case LY_STMT_OUTPUT:
2388 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2389 break;
2390
2391 case LY_STMT_TYPEDEF:
2392 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2393 break;
2394 case LY_STMT_GROUPING:
2395 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2396 break;
2397 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002398 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 +01002399 break;
2400 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002401 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002402 return LY_EVALID;
2403 }
2404 }
2405
2406 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2407 if (!act->input.nodetype) {
2408 act->input.nodetype = LYS_INPUT;
2409 act->input.parent = &act->node;
2410 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2411 }
2412 if (!act->output.nodetype) {
2413 act->output.nodetype = LYS_OUTPUT;
2414 act->output.parent = &act->node;
2415 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2416 }
2417
2418 return LY_SUCCESS;
2419}
2420
2421/**
2422 * @brief Parse the notification statement.
2423 *
2424 * @param[in] ctx parser context.
2425 * @param[in] stmt Source statement data from the parsed extension instance.
2426 * @param[in] parent Parent node to connect to (not into).
2427 * @param[in,out] notifs Notifications to add to.
2428 *
2429 * @return LY_ERR values.
2430 */
2431static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002432lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002433 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002434{
2435 struct lysp_node_notif *notif;
2436
2437 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2438
2439 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2440
2441 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2442 notif->nodetype = LYS_NOTIF;
2443 notif->parent = parent;
2444
2445 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2446 switch (child->kw) {
2447 case LY_STMT_DESCRIPTION:
2448 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2449 break;
2450 case LY_STMT_IF_FEATURE:
2451 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2452 break;
2453 case LY_STMT_REFERENCE:
2454 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2455 break;
2456 case LY_STMT_STATUS:
2457 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2458 break;
2459
2460 case LY_STMT_ANYDATA:
2461 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2462 /* fall through */
2463 case LY_STMT_ANYXML:
2464 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2465 break;
2466 case LY_STMT_CHOICE:
2467 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2468 break;
2469 case LY_STMT_CONTAINER:
2470 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2471 break;
2472 case LY_STMT_LEAF:
2473 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2474 break;
2475 case LY_STMT_LEAF_LIST:
2476 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2477 break;
2478 case LY_STMT_LIST:
2479 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2480 break;
2481 case LY_STMT_USES:
2482 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2483 break;
2484
2485 case LY_STMT_MUST:
2486 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2487 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2488 break;
2489 case LY_STMT_TYPEDEF:
2490 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2491 break;
2492 case LY_STMT_GROUPING:
2493 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2494 break;
2495 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002496 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002497 break;
2498 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002499 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002500 return LY_EVALID;
2501 }
2502 }
2503
2504 return LY_SUCCESS;
2505}
2506
2507/**
2508 * @brief Parse the grouping statement.
2509 *
2510 * @param[in] ctx parser context.
2511 * @param[in] stmt Source statement data from the parsed extension instance.
2512 * @param[in] parent Parent node to connect to (not into).
2513 * @param[in,out] groupings Groupings to add to.
2514 *
2515 * @return LY_ERR values.
2516 */
2517static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002518lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002519 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002520{
2521 struct lysp_node_grp *grp;
2522
2523 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2524
2525 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2526
2527 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2528 grp->nodetype = LYS_GROUPING;
2529 grp->parent = parent;
2530
2531 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2532 switch (child->kw) {
2533 case LY_STMT_DESCRIPTION:
2534 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2535 break;
2536 case LY_STMT_REFERENCE:
2537 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2538 break;
2539 case LY_STMT_STATUS:
2540 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2541 break;
2542
2543 case LY_STMT_ANYDATA:
2544 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2545 /* fall through */
2546 case LY_STMT_ANYXML:
2547 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2548 break;
2549 case LY_STMT_CHOICE:
2550 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2551 break;
2552 case LY_STMT_CONTAINER:
2553 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2554 break;
2555 case LY_STMT_LEAF:
2556 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2557 break;
2558 case LY_STMT_LEAF_LIST:
2559 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2560 break;
2561 case LY_STMT_LIST:
2562 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2563 break;
2564 case LY_STMT_USES:
2565 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2566 break;
2567
2568 case LY_STMT_TYPEDEF:
2569 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2570 break;
2571 case LY_STMT_ACTION:
2572 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2573 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2574 break;
2575 case LY_STMT_GROUPING:
2576 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2577 break;
2578 case LY_STMT_NOTIFICATION:
2579 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2580 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2581 break;
2582 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002583 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002584 break;
2585 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002586 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002587 return LY_EVALID;
2588 }
2589 }
2590
2591 return LY_SUCCESS;
2592}
2593
2594/**
2595 * @brief Parse the augment statement.
2596 *
2597 * @param[in] ctx parser context.
2598 * @param[in] stmt Source statement data from the parsed extension instance.
2599 * @param[in] parent Parent node to connect to (not into).
2600 * @param[in,out] augments Augments to add to.
2601 *
2602 * @return LY_ERR values.
2603 */
2604static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002605lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002606 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002607{
2608 struct lysp_node_augment *aug;
2609
2610 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2611
2612 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2613
2614 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2615 aug->nodetype = LYS_AUGMENT;
2616 aug->parent = parent;
2617
2618 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2619 switch (child->kw) {
2620 case LY_STMT_DESCRIPTION:
2621 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2622 break;
2623 case LY_STMT_IF_FEATURE:
2624 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2625 break;
2626 case LY_STMT_REFERENCE:
2627 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2628 break;
2629 case LY_STMT_STATUS:
2630 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2631 break;
2632 case LY_STMT_WHEN:
2633 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2634 break;
2635
2636 case LY_STMT_ANYDATA:
2637 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2638 /* fall through */
2639 case LY_STMT_ANYXML:
2640 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2641 break;
2642 case LY_STMT_CASE:
2643 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2644 break;
2645 case LY_STMT_CHOICE:
2646 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2647 break;
2648 case LY_STMT_CONTAINER:
2649 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2650 break;
2651 case LY_STMT_LEAF:
2652 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2653 break;
2654 case LY_STMT_LEAF_LIST:
2655 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2656 break;
2657 case LY_STMT_LIST:
2658 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2659 break;
2660 case LY_STMT_USES:
2661 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2662 break;
2663
2664 case LY_STMT_ACTION:
2665 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2666 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2667 break;
2668 case LY_STMT_NOTIFICATION:
2669 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2670 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2671 break;
2672 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002673 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002674 break;
2675 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002676 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002677 return LY_EVALID;
2678 }
2679 }
2680
2681 return LY_SUCCESS;
2682}
2683
2684/**
2685 * @brief Parse the uses statement.
2686 *
2687 * @param[in] ctx parser context.
2688 * @param[in] stmt Source statement data from the parsed extension instance.
2689 * @param[in] parent Parent node to connect to (not into).
2690 * @param[in,out] siblings Siblings to add to.
2691 *
2692 * @return LY_ERR values.
2693 */
2694static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002695lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002696 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002697{
2698 struct lysp_node_uses *uses;
2699
2700 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2701
2702 /* create uses structure */
2703 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2704
2705 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2706 uses->nodetype = LYS_USES;
2707 uses->parent = parent;
2708
2709 /* parse substatements */
2710 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2711 switch (child->kw) {
2712 case LY_STMT_DESCRIPTION:
2713 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2714 break;
2715 case LY_STMT_IF_FEATURE:
2716 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2717 break;
2718 case LY_STMT_REFERENCE:
2719 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2720 break;
2721 case LY_STMT_STATUS:
2722 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2723 break;
2724 case LY_STMT_WHEN:
2725 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2726 break;
2727
2728 case LY_STMT_REFINE:
2729 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2730 break;
2731 case LY_STMT_AUGMENT:
2732 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2733 break;
2734 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002735 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002736 break;
2737 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002738 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002739 return LY_EVALID;
2740 }
2741 }
2742
2743 return LY_SUCCESS;
2744}
2745
2746/**
2747 * @brief Parse the case statement.
2748 *
2749 * @param[in] ctx parser context.
2750 * @param[in] stmt Source statement data from the parsed extension instance.
2751 * @param[in] parent Parent node to connect to (not into).
2752 * @param[in,out] siblings Siblings to add to.
2753 *
2754 * @return LY_ERR values.
2755 */
2756static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002757lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002758 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002759{
2760 struct lysp_node_case *cas;
2761
2762 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2763
2764 /* create new case structure */
2765 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2766
2767 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2768 cas->nodetype = LYS_CASE;
2769 cas->parent = parent;
2770
2771 /* parse substatements */
2772 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2773 switch (child->kw) {
2774 case LY_STMT_DESCRIPTION:
2775 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2776 break;
2777 case LY_STMT_IF_FEATURE:
2778 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2779 break;
2780 case LY_STMT_REFERENCE:
2781 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2782 break;
2783 case LY_STMT_STATUS:
2784 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2785 break;
2786 case LY_STMT_WHEN:
2787 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2788 break;
2789
2790 case LY_STMT_ANYDATA:
2791 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2792 /* fall through */
2793 case LY_STMT_ANYXML:
2794 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2795 break;
2796 case LY_STMT_CHOICE:
2797 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2798 break;
2799 case LY_STMT_CONTAINER:
2800 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2801 break;
2802 case LY_STMT_LEAF:
2803 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2804 break;
2805 case LY_STMT_LEAF_LIST:
2806 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2807 break;
2808 case LY_STMT_LIST:
2809 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2810 break;
2811 case LY_STMT_USES:
2812 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2813 break;
2814 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002815 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002816 break;
2817 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002818 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002819 return LY_EVALID;
2820 }
2821 }
2822 return LY_SUCCESS;
2823}
2824
2825/**
2826 * @brief Parse the choice statement.
2827 *
2828 * @param[in] ctx parser context.
2829 * @param[in] stmt Source statement data from the parsed extension instance.
2830 * @param[in] parent Parent node to connect to (not into).
2831 * @param[in,out] siblings Siblings to add to.
2832 *
2833 * @return LY_ERR values.
2834 */
2835static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002836lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002837 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002838{
2839 struct lysp_node_choice *choice;
2840
2841 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2842
2843 /* create new choice structure */
2844 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2845
2846 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2847 choice->nodetype = LYS_CHOICE;
2848 choice->parent = parent;
2849
2850 /* parse substatements */
2851 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2852 switch (child->kw) {
2853 case LY_STMT_CONFIG:
2854 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2855 break;
2856 case LY_STMT_DESCRIPTION:
2857 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2858 break;
2859 case LY_STMT_IF_FEATURE:
2860 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2861 break;
2862 case LY_STMT_MANDATORY:
2863 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2864 break;
2865 case LY_STMT_REFERENCE:
2866 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2867 break;
2868 case LY_STMT_STATUS:
2869 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2870 break;
2871 case LY_STMT_WHEN:
2872 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2873 break;
2874 case LY_STMT_DEFAULT:
2875 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 +01002876 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002877 break;
2878 case LY_STMT_ANYDATA:
2879 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2880 /* fall through */
2881 case LY_STMT_ANYXML:
2882 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2883 break;
2884 case LY_STMT_CASE:
2885 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2886 break;
2887 case LY_STMT_CHOICE:
2888 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2889 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2890 break;
2891 case LY_STMT_CONTAINER:
2892 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2893 break;
2894 case LY_STMT_LEAF:
2895 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2896 break;
2897 case LY_STMT_LEAF_LIST:
2898 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2899 break;
2900 case LY_STMT_LIST:
2901 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2902 break;
2903 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002904 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002905 break;
2906 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002907 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002908 return LY_EVALID;
2909 }
2910 }
2911 return LY_SUCCESS;
2912}
2913
2914/**
2915 * @brief Parse the container statement.
2916 *
2917 * @param[in] ctx parser context.
2918 * @param[in] stmt Source statement data from the parsed extension instance.
2919 * @param[in] parent Parent node to connect to (not into).
2920 * @param[in,out] siblings Siblings to add to.
2921 *
2922 * @return LY_ERR values.
2923 */
2924static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002925lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002926 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002927{
2928 struct lysp_node_container *cont;
2929
2930 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2931
2932 /* create new container structure */
2933 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2934
2935 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2936 cont->nodetype = LYS_CONTAINER;
2937 cont->parent = parent;
2938
2939 /* parse substatements */
2940 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2941 switch (child->kw) {
2942 case LY_STMT_CONFIG:
2943 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
2944 break;
2945 case LY_STMT_DESCRIPTION:
2946 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
2947 break;
2948 case LY_STMT_IF_FEATURE:
2949 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
2950 break;
2951 case LY_STMT_REFERENCE:
2952 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
2953 break;
2954 case LY_STMT_STATUS:
2955 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
2956 break;
2957 case LY_STMT_WHEN:
2958 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
2959 break;
2960 case LY_STMT_PRESENCE:
2961 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
2962 break;
2963 case LY_STMT_ANYDATA:
2964 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
2965 /* fall through */
2966 case LY_STMT_ANYXML:
2967 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
2968 break;
2969 case LY_STMT_CHOICE:
2970 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
2971 break;
2972 case LY_STMT_CONTAINER:
2973 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
2974 break;
2975 case LY_STMT_LEAF:
2976 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
2977 break;
2978 case LY_STMT_LEAF_LIST:
2979 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
2980 break;
2981 case LY_STMT_LIST:
2982 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
2983 break;
2984 case LY_STMT_USES:
2985 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
2986 break;
2987
2988 case LY_STMT_TYPEDEF:
2989 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
2990 break;
2991 case LY_STMT_MUST:
2992 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
2993 break;
2994 case LY_STMT_ACTION:
2995 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
2996 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
2997 break;
2998 case LY_STMT_GROUPING:
2999 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3000 break;
3001 case LY_STMT_NOTIFICATION:
3002 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3003 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3004 break;
3005 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003006 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003007 break;
3008 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003009 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003010 return LY_EVALID;
3011 }
3012 }
3013
3014 return LY_SUCCESS;
3015}
3016
3017/**
3018 * @brief Parse the list statement.
3019 *
3020 * @param[in] ctx parser context.
3021 * @param[in] stmt Source statement data from the parsed extension instance.
3022 * @param[in] parent Parent node to connect to (not into).
3023 * @param[in,out] siblings Siblings to add to.
3024 *
3025 * @return LY_ERR values.
3026 */
3027static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003028lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003029 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003030{
3031 struct lysp_node_list *list;
3032
3033 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3034
3035 /* create new list structure */
3036 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3037
3038 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3039 list->nodetype = LYS_LIST;
3040 list->parent = parent;
3041
3042 /* parse substatements */
3043 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3044 switch (child->kw) {
3045 case LY_STMT_CONFIG:
3046 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3047 break;
3048 case LY_STMT_DESCRIPTION:
3049 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3050 break;
3051 case LY_STMT_IF_FEATURE:
3052 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3053 break;
3054 case LY_STMT_REFERENCE:
3055 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3056 break;
3057 case LY_STMT_STATUS:
3058 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3059 break;
3060 case LY_STMT_WHEN:
3061 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3062 break;
3063 case LY_STMT_KEY:
3064 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3065 break;
3066 case LY_STMT_MAX_ELEMENTS:
3067 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3068 break;
3069 case LY_STMT_MIN_ELEMENTS:
3070 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3071 break;
3072 case LY_STMT_ORDERED_BY:
3073 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3074 break;
3075 case LY_STMT_UNIQUE:
3076 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3077 break;
3078
3079 case LY_STMT_ANYDATA:
3080 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3081 /* fall through */
3082 case LY_STMT_ANYXML:
3083 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3084 break;
3085 case LY_STMT_CHOICE:
3086 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3087 break;
3088 case LY_STMT_CONTAINER:
3089 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3090 break;
3091 case LY_STMT_LEAF:
3092 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3093 break;
3094 case LY_STMT_LEAF_LIST:
3095 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3096 break;
3097 case LY_STMT_LIST:
3098 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3099 break;
3100 case LY_STMT_USES:
3101 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3102 break;
3103
3104 case LY_STMT_TYPEDEF:
3105 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3106 break;
3107 case LY_STMT_MUST:
3108 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3109 break;
3110 case LY_STMT_ACTION:
3111 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3112 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3113 break;
3114 case LY_STMT_GROUPING:
3115 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3116 break;
3117 case LY_STMT_NOTIFICATION:
3118 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3119 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3120 break;
3121 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003122 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003123 break;
3124 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003125 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003126 return LY_EVALID;
3127 }
3128 }
3129
3130 return LY_SUCCESS;
3131}
3132
Michal Vasko193dacd2022-10-13 08:43:05 +02003133/**
3134 * @brief Parse generic statement structure into a specific parsed-schema structure.
3135 *
3136 * @param[in] pctx Parse context of the @p stmt being processed.
3137 * @param[in] stmt Generic statement structure to process.
3138 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3139 * @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.
3140 * @return LY_ERR value.
3141 */
3142static LY_ERR
3143lysp_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 +02003144{
Radek Krejciad5963b2019-09-06 16:03:05 +02003145 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003146 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003147
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003148 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003149 case LY_STMT_NOTIFICATION:
3150 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3151 break;
3152 case LY_STMT_INPUT:
3153 case LY_STMT_OUTPUT: {
3154 struct lysp_node_action_inout *inout;
3155
3156 *result = inout = calloc(1, sizeof *inout);
3157 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3158 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3159 break;
3160 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003161 case LY_STMT_ACTION:
3162 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003163 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003164 break;
3165 case LY_STMT_ANYDATA:
3166 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003167 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003168 break;
3169 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003170 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003171 break;
3172 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003173 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003174 break;
3175 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003176 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003177 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003178 case LY_STMT_CONTAINER:
3179 ret = lysp_stmt_container(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_GROUPING:
3182 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3183 break;
3184 case LY_STMT_LEAF:
3185 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3186 break;
3187 case LY_STMT_LEAF_LIST:
3188 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3189 break;
3190 case LY_STMT_LIST:
3191 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3192 break;
3193 case LY_STMT_USES:
3194 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3195 break;
3196 case LY_STMT_BASE:
3197 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3198 break;
3199 case LY_STMT_ARGUMENT:
3200 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003201 case LY_STMT_CONTACT:
3202 case LY_STMT_DESCRIPTION:
3203 case LY_STMT_ERROR_APP_TAG:
3204 case LY_STMT_ERROR_MESSAGE:
3205 case LY_STMT_KEY:
3206 case LY_STMT_NAMESPACE:
3207 case LY_STMT_ORGANIZATION:
3208 case LY_STMT_PRESENCE:
3209 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003210 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003211 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003212 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003213 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003214 case LY_STMT_BIT:
3215 case LY_STMT_ENUM:
3216 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3217 break;
3218 case LY_STMT_CONFIG:
3219 assert(*result);
3220 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003221 break;
3222 case LY_STMT_DEFAULT:
3223 case LY_STMT_IF_FEATURE:
3224 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003225 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3226 break;
3227 case LY_STMT_DEVIATE:
3228 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3229 break;
3230 case LY_STMT_DEVIATION:
3231 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3232 break;
3233 case LY_STMT_EXTENSION:
3234 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003235 break;
3236 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003237 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3238 break;
3239 case LY_STMT_FEATURE:
3240 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003241 break;
3242 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003243 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003244 break;
3245 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003246 case LY_STMT_RANGE: {
3247 struct lysp_restr *restr;
3248
3249 *result = restr = calloc(1, sizeof *restr);
3250 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3251
3252 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003253 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003254 }
3255 case LY_STMT_MUST:
3256 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3257 break;
3258 case LY_STMT_IDENTITY:
3259 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3260 break;
3261 case LY_STMT_IMPORT:
3262 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3263 break;
3264 case LY_STMT_INCLUDE:
3265 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003266 break;
3267 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003268 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003269 break;
3270 case LY_STMT_MAX_ELEMENTS:
3271 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003272 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003273 break;
3274 case LY_STMT_MIN_ELEMENTS:
3275 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003276 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003277 break;
3278 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003279 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003280 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003281 case LY_STMT_MODULE: {
3282 struct lysp_module *mod;
3283
3284 *result = mod = calloc(1, sizeof *mod);
3285 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3286 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003287 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003288 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003289 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003290 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003291 break;
3292 case LY_STMT_PATH: {
3293 const char *str_path = NULL;
3294
Michal Vasko193dacd2022-10-13 08:43:05 +02003295 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3296 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003297 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003298 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003299 break;
3300 }
3301 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003302 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003303 break;
3304 case LY_STMT_POSITION:
3305 case LY_STMT_VALUE:
3306 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003307 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003308 break;
3309 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003310 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003311 break;
3312 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003313 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003314 break;
3315 case LY_STMT_REQUIRE_INSTANCE:
3316 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003317 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3318 break;
3319 case LY_STMT_REVISION:
3320 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003321 break;
Michal Vasko69730152020-10-09 16:30:07 +02003322 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003323 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003324 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003325 case LY_STMT_SUBMODULE: {
3326 struct lysp_submodule *submod;
3327
3328 *result = submod = calloc(1, sizeof *submod);
3329 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3330 ret = lysp_stmt_submodule(pctx, stmt, submod);
3331 break;
3332 }
Radek Krejci335332a2019-09-05 13:03:35 +02003333 case LY_STMT_TYPE: {
3334 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003335
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003336 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003337 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3338 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003339 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003340 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003341 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003342 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003343 break;
3344 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003345 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3346 break;
3347 case LY_STMT_YANG_VERSION:
3348 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3349 break;
3350 case LY_STMT_YIN_ELEMENT:
3351 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003352 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003353 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003354 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003355 return LY_EINT;
3356 }
3357
Radek Krejciad5963b2019-09-06 16:03:05 +02003358 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003359}
Michal Vasko59892dd2022-05-13 11:02:30 +02003360
Michal Vasko193dacd2022-10-13 08:43:05 +02003361LY_ERR
3362lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003363{
Michal Vasko193dacd2022-10-13 08:43:05 +02003364 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003365
Michal Vasko193dacd2022-10-13 08:43:05 +02003366 if (!substmt->storage) {
3367 /* nothing to parse, ignored */
3368 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003369 }
3370
Michal Vasko193dacd2022-10-13 08:43:05 +02003371 switch (stmt->kw) {
3372 case LY_STMT_NOTIFICATION:
3373 case LY_STMT_INPUT:
3374 case LY_STMT_OUTPUT:
3375 case LY_STMT_ACTION:
3376 case LY_STMT_RPC:
3377 case LY_STMT_ANYDATA:
3378 case LY_STMT_ANYXML:
3379 case LY_STMT_AUGMENT:
3380 case LY_STMT_CASE:
3381 case LY_STMT_CHOICE:
3382 case LY_STMT_CONTAINER:
3383 case LY_STMT_GROUPING:
3384 case LY_STMT_LEAF:
3385 case LY_STMT_LEAF_LIST:
3386 case LY_STMT_LIST:
3387 case LY_STMT_USES: {
3388 struct lysp_node **pnodes_p, *pnode = NULL;
3389
3390 /* parse the node */
3391 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3392
3393 /* usually is a linked-list of all the parsed schema nodes */
3394 pnodes_p = substmt->storage;
3395 while (*pnodes_p) {
3396 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003397 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003398 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003399
3400 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003401 }
3402 case LY_STMT_BASE:
3403 case LY_STMT_BIT:
3404 case LY_STMT_DEFAULT:
3405 case LY_STMT_DEVIATE:
3406 case LY_STMT_DEVIATION:
3407 case LY_STMT_ENUM:
3408 case LY_STMT_EXTENSION:
3409 case LY_STMT_EXTENSION_INSTANCE:
3410 case LY_STMT_FEATURE:
3411 case LY_STMT_IDENTITY:
3412 case LY_STMT_IF_FEATURE:
3413 case LY_STMT_IMPORT:
3414 case LY_STMT_INCLUDE:
3415 case LY_STMT_MUST:
3416 case LY_STMT_PATTERN:
3417 case LY_STMT_REFINE:
3418 case LY_STMT_REVISION:
3419 case LY_STMT_TYPEDEF:
3420 case LY_STMT_UNIQUE:
3421 /* parse, sized array */
3422 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003423 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003424
3425 case LY_STMT_ARGUMENT:
3426 case LY_STMT_BELONGS_TO:
3427 case LY_STMT_CONTACT:
3428 case LY_STMT_DESCRIPTION:
3429 case LY_STMT_ERROR_APP_TAG:
3430 case LY_STMT_ERROR_MESSAGE:
3431 case LY_STMT_FRACTION_DIGITS:
3432 case LY_STMT_KEY:
3433 case LY_STMT_LENGTH:
3434 case LY_STMT_MANDATORY:
3435 case LY_STMT_MAX_ELEMENTS:
3436 case LY_STMT_MIN_ELEMENTS:
3437 case LY_STMT_MODIFIER:
3438 case LY_STMT_MODULE:
3439 case LY_STMT_NAMESPACE:
3440 case LY_STMT_ORGANIZATION:
3441 case LY_STMT_PATH:
3442 case LY_STMT_POSITION:
3443 case LY_STMT_PREFIX:
3444 case LY_STMT_PRESENCE:
3445 case LY_STMT_RANGE:
3446 case LY_STMT_REFERENCE:
3447 case LY_STMT_REQUIRE_INSTANCE:
3448 case LY_STMT_REVISION_DATE:
3449 case LY_STMT_SUBMODULE:
3450 case LY_STMT_TYPE:
3451 case LY_STMT_UNITS:
3452 case LY_STMT_VALUE:
3453 case LY_STMT_WHEN:
3454 case LY_STMT_YANG_VERSION:
3455 case LY_STMT_YIN_ELEMENT:
3456 /* single item */
3457 if (*(void **)substmt->storage) {
3458 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3459 rc = LY_EVALID;
3460 goto cleanup;
3461 }
3462
3463 /* parse */
3464 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003465 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003466
3467 case LY_STMT_CONFIG:
3468 /* single item */
3469 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3470 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3471 rc = LY_EVALID;
3472 goto cleanup;
3473 }
3474
3475 /* parse */
3476 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3477 break;
3478
3479 case LY_STMT_ORDERED_BY:
3480 /* single item */
3481 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3482 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3483 rc = LY_EVALID;
3484 goto cleanup;
3485 }
3486
3487 /* parse */
3488 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3489 break;
3490
3491 case LY_STMT_STATUS:
3492 /* single item */
3493 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3494 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3495 rc = LY_EVALID;
3496 goto cleanup;
3497 }
3498
3499 /* parse */
3500 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3501 break;
3502
Michal Vasko59892dd2022-05-13 11:02:30 +02003503 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003504 LOGINT(PARSER_CTX(pctx));
3505 rc = LY_EINT;
3506 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003507 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003508
3509cleanup:
3510 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003511}