blob: c164fdfbb7694f75db5d62ed29acad1336b20d76 [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
Michal Vasko59892dd2022-05-13 11:02:30 +020041#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020042#include "dict.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020043#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010044#include "log.h"
Michal Vasko8f702ee2024-02-20 15:44:24 +010045#include "ly_common.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 Vasko820efe82023-05-12 15:47:43 +020049#include "schema_compile_node.h"
Michal Vasko193dacd2022-10-13 08:43:05 +020050#include "schema_features.h"
Radek Krejci77114102021-03-10 15:21:57 +010051#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020052#include "tree.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020053#include "tree_data.h"
54#include "tree_data_internal.h"
Radek Krejci335332a2019-09-05 13:03:35 +020055#include "tree_schema.h"
56#include "tree_schema_internal.h"
57
Michal Vasko59892dd2022-05-13 11:02:30 +020058void
59lyd_ctx_free(struct lyd_ctx *lydctx)
60{
61 ly_set_erase(&lydctx->node_types, NULL);
62 ly_set_erase(&lydctx->meta_types, NULL);
63 ly_set_erase(&lydctx->node_when, NULL);
Michal Vasko135719f2022-08-25 12:18:17 +020064 ly_set_erase(&lydctx->ext_node, free);
Michal Vasko59892dd2022-05-13 11:02:30 +020065 ly_set_erase(&lydctx->ext_val, free);
66}
67
68LY_ERR
Michal Vasko820efe82023-05-12 15:47:43 +020069lyd_parser_notif_eventtime_validate(const struct lyd_node *node)
70{
71 LY_ERR rc = LY_SUCCESS;
72 struct ly_ctx *ctx = (struct ly_ctx *)LYD_CTX(node);
73 struct lysc_ctx cctx;
74 const struct lys_module *mod;
75 LY_ARRAY_COUNT_TYPE u;
76 struct ly_err_item *err = NULL;
77 struct lysp_type *type_p = NULL;
78 struct lysc_pattern **patterns = NULL;
79 const char *value;
80
81 LYSC_CTX_INIT_CTX(cctx, ctx);
82
83 /* get date-and-time parsed type */
84 mod = ly_ctx_get_module_latest(ctx, "ietf-yang-types");
85 assert(mod);
86 LY_ARRAY_FOR(mod->parsed->typedefs, u) {
87 if (!strcmp(mod->parsed->typedefs[u].name, "date-and-time")) {
88 type_p = &mod->parsed->typedefs[u].type;
89 break;
90 }
91 }
92 assert(type_p);
93
94 /* compile patterns */
95 assert(type_p->patterns);
96 LY_CHECK_GOTO(rc = lys_compile_type_patterns(&cctx, type_p->patterns, NULL, &patterns), cleanup);
97
98 /* validate */
99 value = lyd_get_value(node);
100 rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err);
101
102cleanup:
103 FREE_ARRAY(&cctx.free_ctx, patterns, lysc_pattern_free);
104 if (rc && err) {
Michal Vasko7a266772024-01-23 11:02:38 +0100105 ly_err_print(ctx, err);
Michal Vasko820efe82023-05-12 15:47:43 +0200106 ly_err_free(err);
107 LOGVAL(ctx, LYVE_DATA, "Invalid \"eventTime\" in the notification.");
108 }
109 return rc;
110}
111
112LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +0200113lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op)
114{
115 const struct lyd_node *iter;
116
117 *op = NULL;
118
119 if (!parent) {
120 /* no parent, nothing to look for */
121 return LY_SUCCESS;
122 }
123
124 /* we need to find the operation node if it already exists */
125 for (iter = parent; iter; iter = lyd_parent(iter)) {
126 if (iter->schema && (iter->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
127 break;
128 }
129 }
130
131 if (!iter) {
132 /* no operation found */
133 return LY_SUCCESS;
134 }
135
Michal Vaskoe3ed7dc2022-11-30 11:39:44 +0100136 if (!(int_opts & LYD_INTOPT_ANY)) {
137 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
138 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
139 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
140 return LY_EINVAL;
141 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
142 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
143 iter->schema->name);
144 return LY_EINVAL;
145 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
146 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
147 iter->schema->name);
148 return LY_EINVAL;
149 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
150 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
151 iter->schema->name);
152 return LY_EINVAL;
153 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200154 }
155
156 *op = (struct lyd_node *)iter;
157 return LY_SUCCESS;
158}
159
Michal Vaskoa878a892023-08-18 12:22:07 +0200160const struct lysc_node *
161lyd_parser_node_schema(const struct lyd_node *node)
162{
163 uint32_t i;
164 const struct lyd_node *iter;
165 const struct lysc_node *schema = NULL;
166 const struct lys_module *mod;
167
168 if (!node) {
169 return NULL;
170 } else if (node->schema) {
171 /* simplest case */
172 return node->schema;
173 }
174
175 /* find the first schema node in the parsed nodes */
176 i = ly_log_location_dnode_count();
177 if (i) {
178 do {
179 --i;
180 if (ly_log_location_dnode(i)->schema) {
181 /* this node is processed */
182 schema = ly_log_location_dnode(i)->schema;
183 ++i;
184 break;
185 }
186 } while (i);
187 }
188
189 /* get schema node of an opaque node */
190 do {
191 /* get next data node */
192 if (i == ly_log_location_dnode_count()) {
193 iter = node;
194 } else {
195 iter = ly_log_location_dnode(i);
196 }
197 assert(!iter->schema);
198
199 /* get module */
Michal Vasko420cc252023-08-24 08:14:24 +0200200 mod = lyd_node_module(iter);
Michal Vaskoa878a892023-08-18 12:22:07 +0200201 if (!mod) {
202 /* unknown module, no schema node */
203 schema = NULL;
204 break;
205 }
206
207 /* get schema node */
208 schema = lys_find_child(schema, mod, LYD_NAME(iter), 0, 0, 0);
209
210 /* move to the descendant */
211 ++i;
212 } while (schema && (iter != node));
213
214 return schema;
215}
216
Michal Vasko59892dd2022-05-13 11:02:30 +0200217LY_ERR
218lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
219{
220 LY_ERR rc = LY_SUCCESS;
221
Michal Vasko7a266772024-01-23 11:02:38 +0100222 LOG_LOCSET(snode, NULL);
Michal Vasko59892dd2022-05-13 11:02:30 +0200223
224 if (lydctx->int_opts & LYD_INTOPT_ANY) {
225 /* nothing to check, everything is allowed */
226 goto cleanup;
227 }
228
229 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
230 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
231 rc = LY_EVALID;
232 goto cleanup;
233 }
234
235 if (snode->nodetype == LYS_RPC) {
236 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
237 if (lydctx->op_node) {
238 goto error_node_dup;
239 }
240 } else {
241 goto error_node_inval;
242 }
243 } else if (snode->nodetype == LYS_ACTION) {
244 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
245 if (lydctx->op_node) {
246 goto error_node_dup;
247 }
248 } else {
249 goto error_node_inval;
250 }
251 } else if (snode->nodetype == LYS_NOTIF) {
252 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
253 if (lydctx->op_node) {
254 goto error_node_dup;
255 }
256 } else {
257 goto error_node_inval;
258 }
259 }
260
261 /* success */
262 goto cleanup;
263
264error_node_dup:
265 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
266 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
267 lydctx->op_node->schema->name);
268 rc = LY_EVALID;
269 goto cleanup;
270
271error_node_inval:
272 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
273 snode->name);
274 rc = LY_EVALID;
275
276cleanup:
Michal Vasko7a266772024-01-23 11:02:38 +0100277 LOG_LOCBACK(1, 0);
Michal Vasko59892dd2022-05-13 11:02:30 +0200278 return rc;
279}
280
281LY_ERR
282lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
283 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
284{
Michal Vasko9dbb91d2023-01-30 13:59:22 +0100285 LY_ERR r;
Michal Vasko59892dd2022-05-13 11:02:30 +0200286 ly_bool incomplete;
Michal Vaskoa5c4fa42024-02-26 14:04:00 +0100287 ly_bool store_only = (lydctx->parse_opts & LYD_PARSE_STORE_ONLY) == LYD_PARSE_STORE_ONLY ? 1 : 0;
Michal Vasko59892dd2022-05-13 11:02:30 +0200288
stewegd4cde642024-02-21 08:34:16 +0100289 if ((r = lyd_create_term(schema, value, value_len, 1, store_only, dynamic, format, prefix_data,
290 hints, &incomplete, node))) {
Michal Vasko9dbb91d2023-01-30 13:59:22 +0100291 if (lydctx->data_ctx->ctx != schema->module->ctx) {
292 /* move errors to the main context */
293 ly_err_move(schema->module->ctx, (struct ly_ctx *)lydctx->data_ctx->ctx);
294 }
295 return r;
296 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200297
298 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
299 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
300 }
301 return LY_SUCCESS;
302}
303
304LY_ERR
305lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
306 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
307 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
308{
Michal Vaskodd03ff12023-09-11 10:30:48 +0200309 LY_ERR rc = LY_SUCCESS;
310 char *dpath = NULL, *path = NULL;
Michal Vasko59892dd2022-05-13 11:02:30 +0200311 ly_bool incomplete;
312 struct lyd_meta *first = NULL;
Michal Vaskoa5c4fa42024-02-26 14:04:00 +0100313 ly_bool store_only = (lydctx->parse_opts & LYD_PARSE_STORE_ONLY) == LYD_PARSE_STORE_ONLY ? 1 : 0;
Michal Vasko59892dd2022-05-13 11:02:30 +0200314
315 if (meta && *meta) {
316 /* remember the first metadata */
317 first = *meta;
318 }
319
Michal Vaskodd03ff12023-09-11 10:30:48 +0200320 /* generate path to the metadata */
321 LY_CHECK_RET(ly_vlog_build_data_path(lydctx->data_ctx->ctx, &dpath));
322 if (asprintf(&path, "%s/@%s:%.*s", dpath, mod->name, (int)name_len, name) == -1) {
323 LOGMEM(lydctx->data_ctx->ctx);
324 rc = LY_EMEM;
325 goto cleanup;
326 }
Michal Vasko7a266772024-01-23 11:02:38 +0100327 ly_log_location(NULL, NULL, path, NULL);
Michal Vaskodd03ff12023-09-11 10:30:48 +0200328
stewegd4cde642024-02-21 08:34:16 +0100329 LY_CHECK_GOTO(rc = lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, 1, store_only, dynamic, format,
Michal Vasko989cdb42023-10-06 15:32:37 +0200330 prefix_data, hints, ctx_node, 0, &incomplete), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +0200331
332 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
Michal Vaskodd03ff12023-09-11 10:30:48 +0200333 LY_CHECK_GOTO(rc = ly_set_add(&lydctx->meta_types, *meta, 1, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +0200334 }
335
336 if (first) {
337 /* always return the first metadata */
338 *meta = first;
339 }
340
Michal Vaskodd03ff12023-09-11 10:30:48 +0200341cleanup:
Michal Vasko7a266772024-01-23 11:02:38 +0100342 ly_log_location_revert(0, 0, 1, 0);
Michal Vaskodd03ff12023-09-11 10:30:48 +0200343 free(dpath);
344 free(path);
345 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +0200346}
347
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200348LY_ERR
349lyd_parse_check_keys(struct lyd_node *node)
350{
351 const struct lysc_node *skey = NULL;
352 const struct lyd_node *key;
353
354 assert(node->schema->nodetype == LYS_LIST);
355
356 key = lyd_child(node);
357 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
358 if (!key || (key->schema != skey)) {
359 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
360 return LY_EVALID;
361 }
362
363 key = key->next;
364 }
365
366 return LY_SUCCESS;
367}
368
369LY_ERR
370lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
371 struct lysc_ext_instance *ext)
372{
aPieceked39cbe2023-11-06 14:20:27 +0100373 struct lyd_meta *meta2, *prev_meta = NULL, *next_meta = NULL;
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200374 struct lyd_ctx_ext_val *ext_val;
375
Michal Vaskobc9f76f2022-12-01 10:31:38 +0100376 if (lydctx->parse_opts & LYD_PARSE_NO_NEW) {
377 node->flags &= ~LYD_NEW;
378 }
379
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200380 if (lysc_has_when(node->schema)) {
Michal Vaskofbb48c22022-11-30 13:28:03 +0100381 if (lydctx->parse_opts & LYD_PARSE_WHEN_TRUE) {
382 /* the condition was true before */
383 node->flags |= LYD_WHEN_TRUE;
384 }
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200385 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
386 /* remember we need to evaluate this node's when */
387 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
388 }
389 }
390
391 LY_LIST_FOR(*meta, meta2) {
392 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
393 meta2->value.boolean) {
394 /* node is default according to the metadata */
395 node->flags |= LYD_DEFAULT;
396
aPieceked39cbe2023-11-06 14:20:27 +0100397 next_meta = meta2->next;
398
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200399 /* delete the metadata */
aPieceked39cbe2023-11-06 14:20:27 +0100400 if (meta != &node->meta) {
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200401 *meta = (*meta)->next;
402 }
403 lyd_free_meta_single(meta2);
aPieceked39cbe2023-11-06 14:20:27 +0100404 if (prev_meta) {
405 prev_meta->next = next_meta;
406 }
Michal Vasko4754d4a2022-12-01 10:11:21 +0100407
408 /* update dflt flag for all parent NP containers */
409 lyd_cont_set_dflt(lyd_parent(node));
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200410 break;
411 }
412
413 prev_meta = meta2;
414 }
415
416 if (ext) {
417 /* parsed for an extension */
418 node->flags |= LYD_EXT;
419
420 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
421 /* rememeber for validation */
422 ext_val = malloc(sizeof *ext_val);
423 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
424 ext_val->ext = ext;
425 ext_val->sibling = node;
426 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
427 }
428 }
429
430 return LY_SUCCESS;
431}
432
Michal Vasko193dacd2022-10-13 08:43:05 +0200433void
434lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
435{
436 char path[PATH_MAX];
437
438#ifndef __APPLE__
439 char proc_path[32];
440 int len;
441#endif
442
443 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
444 if (*filepath) {
445 /* filepath already set */
446 return;
447 }
448
449 switch (in->type) {
450 case LY_IN_FILEPATH:
451 if (realpath(in->method.fpath.filepath, path) != NULL) {
452 lydict_insert(ctx, path, 0, filepath);
453 } else {
454 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
455 }
456
457 break;
458 case LY_IN_FD:
459#ifdef __APPLE__
460 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
461 lydict_insert(ctx, path, 0, filepath);
462 }
463#elif defined _WIN32
464 HANDLE h = _get_osfhandle(in->method.fd);
465 FILE_NAME_INFO info;
Michal Vasko2bf4af42023-01-04 12:08:38 +0100466
Michal Vasko193dacd2022-10-13 08:43:05 +0200467 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
468 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
Michal Vasko2bf4af42023-01-04 12:08:38 +0100469
Michal Vasko193dacd2022-10-13 08:43:05 +0200470 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
471 lydict_insert(ctx, buf, len, filepath);
472 }
473#else
474 /* get URI if there is /proc */
475 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
476 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
477 lydict_insert(ctx, path, len, filepath);
478 }
479#endif
480 break;
481 case LY_IN_MEMORY:
482 case LY_IN_FILE:
483 /* nothing to do */
484 break;
485 default:
486 LOGINT(ctx);
487 break;
488 }
489}
490
Michal Vaskod0625d72022-10-06 15:02:50 +0200491static 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 +0100492 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200493static 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 +0100494 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200495static 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 +0100496 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200497static 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 +0100498 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200499static 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 +0100500 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200501static 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 +0100502 struct lysp_node **siblings);
503
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100504/**
505 * @brief Validate stmt string value.
506 *
507 * @param[in] ctx Parser context.
508 * @param[in] val_type String value type.
509 * @param[in] val Value to validate.
510 * @return LY_ERR value.
511 */
Radek Krejci335332a2019-09-05 13:03:35 +0200512static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200513lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200514{
Radek Krejci857189e2020-09-01 13:26:36 +0200515 uint8_t prefix = 0;
516 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200517 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200518 size_t utf8_char_len;
519
Michal Vaskocfa1a962023-02-27 09:28:45 +0100520 if (!val) {
521 if (val_type == Y_MAYBE_STR_ARG) {
522 /* fine */
523 return LY_SUCCESS;
524 }
525
526 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Missing an expected string.");
527 return LY_EVALID;
528 }
529
Radek Krejci335332a2019-09-05 13:03:35 +0200530 while (*val) {
531 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200532 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200533
534 switch (val_type) {
535 case Y_IDENTIF_ARG:
536 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
537 break;
538 case Y_PREF_IDENTIF_ARG:
539 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
540 break;
541 case Y_STR_ARG:
542 case Y_MAYBE_STR_ARG:
543 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
544 break;
545 }
546 first = 0;
547 }
548
549 return LY_SUCCESS;
550}
551
552/**
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100553 * @brief Duplicate statement siblings, recursively.
554 *
555 * @param[in] ctx Parser context.
556 * @param[in] stmt Statement to duplicate.
557 * @param[out] first First duplicated statement, the rest follow.
558 * @return LY_ERR value.
559 */
560static LY_ERR
561lysp_stmt_dup(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_stmt **first)
562{
563 struct lysp_stmt *child, *last = NULL;
564
565 LY_LIST_FOR(stmt, stmt) {
566 child = calloc(1, sizeof *child);
567 LY_CHECK_ERR_RET(!child, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
568
569 if (last) {
570 last->next = child;
571 } else {
572 assert(!*first);
573 *first = child;
574 }
575 last = child;
576
577 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &child->stmt));
578 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &child->arg));
579 child->format = stmt->format;
580 LY_CHECK_RET(ly_dup_prefix_data(PARSER_CTX(ctx), stmt->format, stmt->prefix_data, &child->prefix_data));
581 child->flags = stmt->flags;
582 child->kw = stmt->kw;
583
584 /* recursively */
585 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &child->child));
586 }
587
588 return LY_SUCCESS;
589}
590
591/**
Radek Krejci335332a2019-09-05 13:03:35 +0200592 * @brief Parse extension instance.
593 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100594 * @param[in] ctx parser context.
595 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100596 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200597 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
598 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200599 * @return LY_ERR values.
600 */
601static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200602lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200603 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200604{
605 struct lysp_ext_instance *e;
606
Michal Vaskob36053d2020-03-26 15:49:30 +0100607 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200608
609 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200610 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100611 e->parent_stmt = insubstmt;
612 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200613 e->parsed = NULL;
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100614 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &e->child));
Radek Krejci335332a2019-09-05 13:03:35 +0200615
616 /* get optional argument */
617 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200618 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200619 }
620
621 return LY_SUCCESS;
622}
623
624/**
625 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
626 * description, etc...
627 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100628 * @param[in] ctx parser context.
629 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200630 * @param[in] substmt_index Index of this substatement.
631 * @param[in,out] value Place to store the parsed value.
632 * @param[in] arg Type of the YANG keyword argument (of the value).
633 * @param[in,out] exts Extension instances to add to.
634 *
635 * @return LY_ERR values.
636 */
637static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200638lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
639 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200640{
Radek Krejci335332a2019-09-05 13:03:35 +0200641 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200642 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200643 return LY_EVALID;
644 }
645
646 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200647 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200648
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100649 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
650 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200651 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100652 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200653 break;
654 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200655 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200656 return LY_EVALID;
657 }
658 }
659 return LY_SUCCESS;
660}
661
662/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200663 * @brief Parse a qname that can have more instances such as if-feature.
664 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100665 * @param[in] ctx parser context.
666 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200667 * @param[in,out] qnames Parsed qnames to add to.
668 * @param[in] arg Type of the expected argument.
669 * @param[in,out] exts Extension instances to add to.
670 *
671 * @return LY_ERR values.
672 */
673static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200674lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
675 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200676{
677 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200678
679 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
680
681 /* allocate new pointer */
682 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
683 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100684 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200685
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100686 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
687 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200688 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100689 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200690 break;
691 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200692 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200693 return LY_EVALID;
694 }
695 }
696 return LY_SUCCESS;
697}
698
699/**
Radek Krejci335332a2019-09-05 13:03:35 +0200700 * @brief Parse a generic text field that can have more instances such as base.
701 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100702 * @param[in] ctx parser context.
703 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200704 * @param[in,out] texts Parsed values to add to.
705 * @param[in] arg Type of the expected argument.
706 * @param[in,out] exts Extension instances to add to.
707 *
708 * @return LY_ERR values.
709 */
710static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200711lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
712 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200713{
714 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200715
716 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
717
718 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100719 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200720 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200721
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100722 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
723 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200724 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100725 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200726 break;
727 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200728 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200729 return LY_EVALID;
730 }
731 }
732 return LY_SUCCESS;
733}
734
735/**
736 * @brief Parse the status statement.
737 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100738 * @param[in] ctx parser context.
739 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200740 * @param[in,out] flags Flags to add to.
741 * @param[in,out] exts Extension instances to add to.
742 *
743 * @return LY_ERR values.
744 */
745static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200746lysp_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 +0200747{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200748 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200749
750 if (*flags & LYS_STATUS_MASK) {
751 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
752 return LY_EVALID;
753 }
754
755 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
756 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100757 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200758 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100759 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200760 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100761 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200762 *flags |= LYS_STATUS_OBSLT;
763 } else {
764 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
765 return LY_EVALID;
766 }
767
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100768 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
769 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200770 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100771 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200772 break;
773 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200774 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200775 return LY_EVALID;
776 }
777 }
778 return LY_SUCCESS;
779}
780
781/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100782 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200783 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100784 * @param[in] ctx parser context.
785 * @param[in] stmt Source statement data from the parsed extension instance.
786 * @param[in,out] when_p When pointer to parse to.
787 *
788 * @return LY_ERR values.
789 */
790static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200791lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100792{
793 LY_ERR ret = LY_SUCCESS;
794 struct lysp_when *when;
795
796 if (*when_p) {
797 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
798 return LY_EVALID;
799 }
800
801 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
802
803 when = calloc(1, sizeof *when);
804 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
805 *when_p = when;
806
807 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
808
809 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
810 switch (child->kw) {
811 case LY_STMT_DESCRIPTION:
812 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
813 break;
814 case LY_STMT_REFERENCE:
815 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
816 break;
817 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100818 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100819 break;
820 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200821 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100822 return LY_EVALID;
823 }
824 }
825 return ret;
826}
827
828/**
829 * @brief Parse the config statement.
830 *
831 * @param[in] ctx parser context.
832 * @param[in] stmt Source statement data from the parsed extension instance.
833 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200834 * @param[in,out] exts Extension instances to add to.
835 *
836 * @return LY_ERR values.
837 */
838static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200839lysp_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 +0200840{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200841 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200842
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100843 if (*flags & LYS_CONFIG_MASK) {
844 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
845 return LY_EVALID;
846 }
847
848 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
849 arg_len = strlen(stmt->arg);
850 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
851 *flags |= LYS_CONFIG_W;
852 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
853 *flags |= LYS_CONFIG_R;
854 } else {
855 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
856 return LY_EVALID;
857 }
858
859 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
860 switch (child->kw) {
861 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100862 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100863 break;
864 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200865 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100866 return LY_EVALID;
867 }
868 }
869
870 return LY_SUCCESS;
871}
872
873/**
874 * @brief Parse the mandatory statement.
875 *
876 * @param[in] ctx parser context.
877 * @param[in] stmt Source statement data from the parsed extension instance.
878 * @param[in,out] flags Flags to add to.
879 * @param[in,out] exts Extension instances to add to.
880 *
881 * @return LY_ERR values.
882 */
883static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200884lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200885 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100886{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200887 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100888
889 if (*flags & LYS_MAND_MASK) {
890 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
891 return LY_EVALID;
892 }
893
894 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
895 arg_len = strlen(stmt->arg);
896 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
897 *flags |= LYS_MAND_TRUE;
898 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
899 *flags |= LYS_MAND_FALSE;
900 } else {
901 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
902 return LY_EVALID;
903 }
904
905 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
906 switch (child->kw) {
907 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100908 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100909 break;
910 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200911 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100912 return LY_EVALID;
913 }
914 }
915
916 return LY_SUCCESS;
917}
918
919/**
920 * @brief Parse a restriction such as range or length.
921 *
922 * @param[in] ctx parser context.
923 * @param[in] stmt Source statement data from the parsed extension instance.
924 * @param[in,out] exts Extension instances to add to.
925 *
926 * @return LY_ERR values.
927 */
928static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200929lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100930{
Radek Krejci335332a2019-09-05 13:03:35 +0200931 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200932 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100933 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200934
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100935 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
936 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200937 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100938 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200939 break;
940 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100941 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200942 break;
943 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100944 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200945 break;
946 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100947 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200948 break;
949 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100950 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200951 break;
952 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200953 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200954 return LY_EVALID;
955 }
956 }
957 return LY_SUCCESS;
958}
959
960/**
961 * @brief Parse a restriction that can have more instances such as must.
962 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100963 * @param[in] ctx parser context.
964 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200965 * @param[in,out] restrs Restrictions to add to.
966 *
967 * @return LY_ERR values.
968 */
969static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200970lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200971{
972 struct lysp_restr *restr;
973
Michal Vaskob36053d2020-03-26 15:49:30 +0100974 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100975 return lysp_stmt_restr(ctx, stmt, restr);
976}
977
978/**
979 * @brief Parse the anydata or anyxml statement.
980 *
981 * @param[in] ctx parser context.
982 * @param[in] stmt Source statement data from the parsed extension instance.
983 * @param[in,out] siblings Siblings to add to.
984 *
985 * @return LY_ERR values.
986 */
987static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200988lysp_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 +0100989{
990 struct lysp_node_anydata *any;
991
992 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
993
994 /* create new structure and insert into siblings */
995 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
996
997 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
998 any->parent = parent;
999
1000 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
1001
1002 /* parse substatements */
1003 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1004 switch (child->kw) {
1005 case LY_STMT_CONFIG:
1006 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
1007 break;
1008 case LY_STMT_DESCRIPTION:
1009 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
1010 break;
1011 case LY_STMT_IF_FEATURE:
1012 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
1013 break;
1014 case LY_STMT_MANDATORY:
1015 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
1016 break;
1017 case LY_STMT_MUST:
1018 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
1019 break;
1020 case LY_STMT_REFERENCE:
1021 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
1022 break;
1023 case LY_STMT_STATUS:
1024 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
1025 break;
1026 case LY_STMT_WHEN:
1027 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
1028 break;
1029 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001030 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001031 break;
1032 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001033 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1034 (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 +01001035 return LY_EVALID;
1036 }
1037 }
1038
1039 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +02001040}
1041
1042/**
1043 * @brief Parse the value or position statement. Substatement of type enum statement.
1044 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001045 * @param[in] ctx parser context.
1046 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001047 * @param[in,out] value Value to write to.
1048 * @param[in,out] flags Flags to write to.
1049 * @param[in,out] exts Extension instances to add to.
1050 *
1051 * @return LY_ERR values.
1052 */
1053static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001054lysp_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 +02001055 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001056{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001057 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001058 char *ptr = NULL;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001059 long long num = 0;
1060 unsigned long long unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +02001061
1062 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001063 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001064 return LY_EVALID;
1065 }
1066 *flags |= LYS_SET_VALUE;
1067
1068 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1069
1070 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001071 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
1072 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001073 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001074 goto error;
1075 }
1076
1077 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001078 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001079 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001080 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001081 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001082 goto error;
1083 }
1084 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001085 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001086 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001087 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001088 goto error;
1089 }
1090 }
1091 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001092 if (ptr - stmt->arg != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001093 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001094 goto error;
1095 }
1096 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001097 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001098 goto error;
1099 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001100 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +02001101 *value = num;
1102 } else {
1103 *value = unum;
1104 }
1105
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001106 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1107 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001108 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001109 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 +02001110 break;
1111 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001112 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001113 return LY_EVALID;
1114 }
1115 }
1116 return LY_SUCCESS;
1117
1118error:
1119 return LY_EVALID;
1120}
1121
1122/**
1123 * @brief Parse the enum or bit statement. Substatement of type statement.
1124 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001125 * @param[in] ctx parser context.
1126 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001127 * @param[in,out] enums Enums or bits to add to.
1128 *
1129 * @return LY_ERR values.
1130 */
1131static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001132lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +02001133{
1134 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +02001135
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001136 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 +02001137
Michal Vaskob36053d2020-03-26 15:49:30 +01001138 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001139
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001140 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +02001141 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
1142 } /* else nothing specific for YANG_BIT */
1143
Radek Krejci011e4aa2020-09-04 15:22:31 +02001144 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +02001145 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +02001146
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001147 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1148 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001149 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001150 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001151 break;
1152 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001153 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001154 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001155 break;
1156 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001157 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001158 break;
1159 case LY_STMT_STATUS:
1160 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
1161 break;
1162 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001163 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1164 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001165 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001166 break;
1167 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +02001168 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1169 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001170 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001171 break;
1172 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001173 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001174 break;
1175 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001176 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001177 return LY_EVALID;
1178 }
1179 }
Michal Vasko193dacd2022-10-13 08:43:05 +02001180
Radek Krejci335332a2019-09-05 13:03:35 +02001181 return LY_SUCCESS;
1182}
1183
1184/**
1185 * @brief Parse the fraction-digits statement. Substatement of type statement.
1186 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001187 * @param[in] ctx parser context.
1188 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001189 * @param[in,out] fracdig Value to write to.
1190 * @param[in,out] exts Extension instances to add to.
1191 *
1192 * @return LY_ERR values.
1193 */
1194static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001195lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001196 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001197{
1198 char *ptr;
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001199 int arg_len;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001200 unsigned long long num;
Radek Krejci335332a2019-09-05 13:03:35 +02001201
1202 if (*fracdig) {
1203 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1204 return LY_EVALID;
1205 }
1206
1207 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1208 arg_len = strlen(stmt->arg);
1209 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1210 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1211 return LY_EVALID;
1212 }
1213
1214 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001215 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001216 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001217 if (ptr - stmt->arg != arg_len) {
Radek Krejci335332a2019-09-05 13:03:35 +02001218 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1219 return LY_EVALID;
1220 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001221 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001222 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1223 return LY_EVALID;
1224 }
1225 *fracdig = num;
1226
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001227 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1228 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001229 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001230 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001231 break;
1232 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001233 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001234 return LY_EVALID;
1235 }
1236 }
1237 return LY_SUCCESS;
1238}
1239
1240/**
1241 * @brief Parse the require-instance statement. Substatement of type statement.
1242 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001243 * @param[in] ctx parser context.
1244 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001245 * @param[in,out] reqinst Value to write to.
1246 * @param[in,out] flags Flags to write to.
1247 * @param[in,out] exts Extension instances to add to.
1248 *
1249 * @return LY_ERR values.
1250 */
1251static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001252lysp_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 +02001253 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001254{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001255 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001256
1257 if (*flags & LYS_SET_REQINST) {
1258 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1259 return LY_EVALID;
1260 }
1261 *flags |= LYS_SET_REQINST;
1262
1263 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1264 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001265 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001266 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001267 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001268 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1269 return LY_EVALID;
1270 }
1271
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001272 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1273 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001274 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001275 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001276 break;
1277 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001278 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001279 return LY_EVALID;
1280 }
1281 }
1282 return LY_SUCCESS;
1283}
1284
1285/**
1286 * @brief Parse the modifier statement. Substatement of type pattern statement.
1287 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001288 * @param[in] ctx parser context.
1289 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001290 * @param[in,out] pat Value to write to.
1291 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001292 * @return LY_ERR values.
1293 */
1294static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001295lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001296 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001297{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001298 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001299 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001300
Radek Krejcif13b87b2020-12-01 22:02:17 +01001301 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001302 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1303 return LY_EVALID;
1304 }
1305
1306 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1307 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001308 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001309 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1310 return LY_EVALID;
1311 }
1312
1313 /* replace the value in the dictionary */
1314 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001315 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001316 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001317 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001318
Radek Krejcif13b87b2020-12-01 22:02:17 +01001319 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1320 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001321 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001322
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001323 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1324 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001325 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001326 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001327 break;
1328 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001329 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001330 return LY_EVALID;
1331 }
1332 }
1333 return LY_SUCCESS;
1334}
1335
1336/**
1337 * @brief Parse the pattern statement. Substatement of type statement.
1338 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001339 * @param[in] ctx parser context.
1340 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001341 * @param[in,out] patterns Restrictions to add to.
1342 *
1343 * @return LY_ERR values.
1344 */
1345static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001346lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001347{
1348 char *buf;
1349 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001350 struct lysp_restr *restr;
1351
1352 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001353 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001354 arg_len = strlen(stmt->arg);
1355
1356 /* add special meaning first byte */
1357 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001358 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001359 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001360 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001361 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001362 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001363 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001364
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001365 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1366 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001367 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001368 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001369 break;
1370 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001371 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001372 break;
1373 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001374 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001375 break;
1376 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001377 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001378 break;
1379 case LY_STMT_MODIFIER:
1380 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001381 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001382 break;
1383 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001384 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001385 break;
1386 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001387 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001388 return LY_EVALID;
1389 }
1390 }
1391 return LY_SUCCESS;
1392}
1393
1394/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001395 * @brief Parse the deviate statement. Substatement of deviation statement.
1396 *
1397 * @param[in] ctx parser context.
1398 * @param[in] stmt Source statement data from the parsed extension instance.
1399 * @param[in,out] devs Array of deviates to add to.
1400 * @param[in,out] exts Extension instances to add to.
1401 * @return LY_ERR values.
1402 */
1403static LY_ERR
1404lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1405{
1406 (void)stmt;
1407 (void)devs;
1408 (void)exts;
1409
1410 /* TODO */
1411 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1412 return LY_EINVAL;
1413}
1414
1415/**
1416 * @brief Parse the deviation statement.
1417 *
1418 * @param[in] ctx parser context.
1419 * @param[in] stmt Source statement data from the parsed extension instance.
1420 * @param[in,out] deviations Array of deviations to add to.
1421 * @return LY_ERR values.
1422 */
1423static LY_ERR
1424lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1425{
1426 struct lysp_deviation *dev;
1427
1428 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1429
1430 /* store nodeid */
1431 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1432 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1433
1434 /* parse substatements */
1435 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1436 switch (child->kw) {
1437 case LY_STMT_DESCRIPTION:
1438 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1439 break;
1440 case LY_STMT_DEVIATE:
1441 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1442 break;
1443 case LY_STMT_REFERENCE:
1444 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1445 break;
1446 case LY_STMT_EXTENSION_INSTANCE:
1447 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1448 break;
1449 default:
1450 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1451 return LY_EVALID;
1452 }
1453 }
1454
1455 return LY_SUCCESS;
1456}
1457
1458/**
1459 * @brief Parse the yang-version statement.
1460 *
1461 * @param[in] ctx parser context.
1462 * @param[in] stmt Source statement data from the parsed extension instance.
1463 * @param[out] version Version to write to.
1464 * @param[in,out] exts Extension instances to add to.
1465 * @return LY_ERR values.
1466 */
1467static LY_ERR
1468lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1469{
1470 if (*version) {
1471 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1472 return LY_EVALID;
1473 }
1474
1475 /* store flag */
1476 if (!strcmp(stmt->arg, "1")) {
1477 *version = LYS_VERSION_1_0;
1478 } else if (!strcmp(stmt->arg, "1.1")) {
1479 *version = LYS_VERSION_1_1;
1480 } else {
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001481 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, (int)strlen(stmt->arg), stmt->arg, "yang-version");
Michal Vasko193dacd2022-10-13 08:43:05 +02001482 return LY_EVALID;
1483 }
1484
1485 /* parse substatements */
1486 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1487 switch (child->kw) {
1488 case LY_STMT_EXTENSION_INSTANCE:
1489 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1490 break;
1491 default:
1492 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1493 return LY_EVALID;
1494 }
1495 }
1496
1497 return LY_SUCCESS;
1498}
1499
1500/**
1501 * @brief Parse the module statement.
1502 *
1503 * @param[in] ctx parser context.
1504 * @param[in] stmt Source statement data from the parsed extension instance.
1505 * @param[in,out] mod Module to fill.
1506 * @return LY_ERR values.
1507 */
1508static LY_ERR
1509lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1510{
1511 (void)stmt;
1512 (void)mod;
1513
1514 /* TODO */
1515 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1516 return LY_EINVAL;
1517}
1518
1519/**
1520 * @brief Parse the submodule statement.
1521 *
1522 * @param[in] ctx parser context.
1523 * @param[in] stmt Source statement data from the parsed extension instance.
1524 * @param[in,out] submod Module to fill.
1525 * @return LY_ERR values.
1526 */
1527static LY_ERR
1528lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1529{
1530 (void)stmt;
1531 (void)submod;
1532
1533 /* TODO */
1534 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1535 return LY_EINVAL;
1536}
1537
1538/**
1539 * @brief Parse the yin-element statement. Substatement of argument statement.
1540 *
1541 * @param[in] ctx parser context.
1542 * @param[in] stmt Source statement data from the parsed extension instance.
1543 * @param[in,out] flags Flags to write to.
1544 * @param[in,out] exts Extension instances to add to.
1545 * @return LY_ERR values.
1546 */
1547static LY_ERR
1548lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1549{
1550 if (*flags & LYS_YINELEM_MASK) {
1551 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1552 return LY_EVALID;
1553 }
1554
1555 /* store flag */
1556 if (!strcmp(stmt->arg, "true")) {
1557 *flags |= LYS_YINELEM_TRUE;
1558 } else if (!strcmp(stmt->arg, "false")) {
1559 *flags |= LYS_YINELEM_FALSE;
1560 } else {
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001561 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, (int)strlen(stmt->arg), stmt->arg, "yin-element");
Michal Vasko193dacd2022-10-13 08:43:05 +02001562 return LY_EVALID;
1563 }
1564
1565 /* parse substatements */
1566 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1567 switch (child->kw) {
1568 case LY_STMT_EXTENSION_INSTANCE:
1569 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1570 break;
1571 default:
1572 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1573 return LY_EVALID;
1574 }
1575 }
1576
1577 return LY_SUCCESS;
1578}
1579
1580/**
1581 * @brief Parse the argument statement. Substatement of extension statement.
1582 *
1583 * @param[in] ctx parser context.
1584 * @param[in] stmt Source statement data from the parsed extension instance.
1585 * @param[in,out] ex Extension to fill.
1586 * @return LY_ERR values.
1587 */
1588static LY_ERR
1589lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1590{
1591 if (ex->argname) {
1592 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1593 return LY_EVALID;
1594 }
1595
1596 /* store argument name */
1597 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1598 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1599
1600 /* parse substatements */
1601 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1602 switch (child->kw) {
1603 case LY_STMT_YIN_ELEMENT:
1604 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1605 break;
1606 case LY_STMT_EXTENSION_INSTANCE:
1607 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1608 break;
1609 default:
1610 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1611 return LY_EVALID;
1612 }
1613 }
1614
1615 return LY_SUCCESS;
1616}
1617
1618/**
1619 * @brief Parse the extension statement.
1620 *
1621 * @param[in] ctx parser context.
1622 * @param[in] stmt Source statement data from the parsed extension instance.
1623 * @param[in,out] extensions Array of extensions to add to.
1624 * @return LY_ERR values.
1625 */
1626static LY_ERR
1627lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1628{
1629 struct lysp_ext *ex;
1630
1631 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1632
1633 /* store name */
1634 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1635 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1636
1637 /* parse substatements */
1638 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1639 switch (child->kw) {
1640 case LY_STMT_DESCRIPTION:
1641 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1642 break;
1643 case LY_STMT_REFERENCE:
1644 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1645 break;
1646 case LY_STMT_STATUS:
1647 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1648 break;
1649 case LY_STMT_ARGUMENT:
1650 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1651 break;
1652 case LY_STMT_EXTENSION_INSTANCE:
1653 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1654 break;
1655 default:
1656 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1657 return LY_EVALID;
1658 }
1659 }
1660
1661 return LY_SUCCESS;
1662}
1663
1664/**
1665 * @brief Parse the feature statement.
1666 *
1667 * @param[in] ctx parser context.
1668 * @param[in] stmt Source statement data from the parsed extension instance.
1669 * @param[in,out] features Array of features to add to.
1670 * @return LY_ERR values.
1671 */
1672static LY_ERR
1673lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1674{
1675 struct lysp_feature *feat;
1676
1677 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1678
1679 /* store name */
1680 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1681 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1682
1683 /* parse substatements */
1684 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1685 switch (child->kw) {
1686 case LY_STMT_DESCRIPTION:
1687 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1688 break;
1689 case LY_STMT_IF_FEATURE:
1690 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1691 break;
1692 case LY_STMT_REFERENCE:
1693 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1694 break;
1695 case LY_STMT_STATUS:
1696 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1697 break;
1698 case LY_STMT_EXTENSION_INSTANCE:
1699 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1700 break;
1701 default:
1702 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1703 return LY_EVALID;
1704 }
1705 }
1706
1707 return LY_SUCCESS;
1708}
1709
1710/**
1711 * @brief Parse the identity statement.
1712 *
1713 * @param[in] ctx parser context.
1714 * @param[in] stmt Source statement data from the parsed extension instance.
1715 * @param[in,out] identities Array of identities to add to.
1716 * @return LY_ERR values.
1717 */
1718static LY_ERR
1719lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1720{
1721 struct lysp_ident *ident;
1722
1723 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1724
1725 /* store name */
1726 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1727 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1728
1729 /* parse substatements */
1730 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1731 switch (child->kw) {
1732 case LY_STMT_DESCRIPTION:
1733 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1734 break;
1735 case LY_STMT_IF_FEATURE:
1736 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1737 break;
1738 case LY_STMT_REFERENCE:
1739 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1740 break;
1741 case LY_STMT_STATUS:
1742 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1743 break;
1744 case LY_STMT_BASE:
1745 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1746 break;
1747 case LY_STMT_EXTENSION_INSTANCE:
1748 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1749 break;
1750 default:
1751 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1752 return LY_EVALID;
1753 }
1754 }
1755
1756 return LY_SUCCESS;
1757}
1758
1759/**
1760 * @brief Parse the import statement.
1761 *
1762 * @param[in] ctx parser context.
1763 * @param[in] stmt Source statement data from the parsed extension instance.
1764 * @param[in,out] imports Array of imports to add to.
1765 * @return LY_ERR values.
1766 */
1767static LY_ERR
1768lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1769{
1770 struct lysp_import *imp;
1771 const char *str = NULL;
1772
1773 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1774
1775 /* store name */
1776 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1777 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1778
1779 /* parse substatements */
1780 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1781 switch (child->kw) {
1782 case LY_STMT_PREFIX:
1783 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1784 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1785 break;
1786 case LY_STMT_DESCRIPTION:
1787 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1788 break;
1789 case LY_STMT_REFERENCE:
1790 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1791 break;
1792 case LY_STMT_REVISION_DATE:
1793 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1794 strcpy(imp->rev, str);
1795 lydict_remove(PARSER_CTX(ctx), str);
1796 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1797 break;
1798 case LY_STMT_EXTENSION_INSTANCE:
1799 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1800 break;
1801 default:
1802 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1803 return LY_EVALID;
1804 }
1805 }
1806
1807 return LY_SUCCESS;
1808}
1809
1810/**
1811 * @brief Parse the include statement.
1812 *
1813 * @param[in] ctx parser context.
1814 * @param[in] stmt Source statement data from the parsed extension instance.
1815 * @param[in,out] includes Array of identities to add to.
1816 * @return LY_ERR values.
1817 */
1818static LY_ERR
1819lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1820{
1821 struct lysp_include *inc;
1822 const char *str = NULL;
1823
1824 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1825
1826 /* store name */
1827 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1828 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1829
1830 /* parse substatements */
1831 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1832 switch (child->kw) {
1833 case LY_STMT_DESCRIPTION:
1834 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1835 break;
1836 case LY_STMT_REFERENCE:
1837 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1838 break;
1839 case LY_STMT_REVISION_DATE:
1840 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1841 strcpy(inc->rev, str);
1842 lydict_remove(PARSER_CTX(ctx), str);
1843 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1844 break;
1845 case LY_STMT_EXTENSION_INSTANCE:
1846 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1847 break;
1848 default:
1849 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1850 return LY_EVALID;
1851 }
1852 }
1853
1854 return LY_SUCCESS;
1855}
1856
1857/**
1858 * @brief Parse the revision statement.
1859 *
1860 * @param[in] ctx parser context.
1861 * @param[in] stmt Source statement data from the parsed extension instance.
1862 * @param[in,out] includes Array of identities to add to.
1863 * @return LY_ERR values.
1864 */
1865static LY_ERR
1866lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1867{
1868 struct lysp_revision *rev;
1869
1870 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1871
1872 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001873 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001874 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001875
1876 /* parse substatements */
1877 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1878 switch (child->kw) {
1879 case LY_STMT_DESCRIPTION:
1880 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1881 break;
1882 case LY_STMT_REFERENCE:
1883 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1884 break;
1885 case LY_STMT_EXTENSION_INSTANCE:
1886 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1887 break;
1888 default:
1889 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1890 return LY_EVALID;
1891 }
1892 }
1893
1894 return LY_SUCCESS;
1895}
1896
1897/**
Radek Krejci335332a2019-09-05 13:03:35 +02001898 * @brief Parse the type statement.
1899 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001900 * @param[in] ctx parser context.
1901 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001902 * @param[in,out] type Type to wrote to.
1903 *
1904 * @return LY_ERR values.
1905 */
1906static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001907lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001908{
1909 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001910 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001911 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001912
1913 if (type->name) {
1914 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1915 return LY_EVALID;
1916 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001917
1918 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001919 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001920 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001921
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001922 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1923 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001924 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001925 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001926 type->flags |= LYS_SET_BASE;
1927 break;
1928 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001929 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001930 type->flags |= LYS_SET_BIT;
1931 break;
1932 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001933 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001934 type->flags |= LYS_SET_ENUM;
1935 break;
1936 case LY_STMT_FRACTION_DIGITS:
1937 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1938 type->flags |= LYS_SET_FRDIGITS;
1939 break;
1940 case LY_STMT_LENGTH:
1941 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001942 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001943 return LY_EVALID;
1944 }
1945 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001946 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001947
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001948 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001949 type->flags |= LYS_SET_LENGTH;
1950 break;
1951 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001952 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001953 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001954 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001955 lydict_remove(PARSER_CTX(ctx), str_path);
1956 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001957 type->flags |= LYS_SET_PATH;
1958 break;
1959 case LY_STMT_PATTERN:
1960 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1961 type->flags |= LYS_SET_PATTERN;
1962 break;
1963 case LY_STMT_RANGE:
1964 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001965 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001966 return LY_EVALID;
1967 }
1968 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001969 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001970
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001971 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001972 type->flags |= LYS_SET_RANGE;
1973 break;
1974 case LY_STMT_REQUIRE_INSTANCE:
1975 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001976 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001977 break;
1978 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001979 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001980 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1981 type->flags |= LYS_SET_TYPE;
1982 break;
1983 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001984 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001985 break;
1986 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001987 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001988 return LY_EVALID;
1989 }
1990 }
1991 return LY_SUCCESS;
1992}
1993
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001994/**
1995 * @brief Parse the leaf statement.
1996 *
1997 * @param[in] ctx parser context.
1998 * @param[in] stmt Source statement data from the parsed extension instance.
1999 * @param[in] parent Parent node to connect to (not into).
2000 * @param[in,out] siblings Siblings to add to.
2001 *
2002 * @return LY_ERR values.
2003 */
2004static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002005lysp_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 +01002006{
2007 struct lysp_node_leaf *leaf;
2008
2009 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2010
2011 /* create new leaf structure */
2012 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
2013 leaf->nodetype = LYS_LEAF;
2014 leaf->parent = parent;
2015
2016 /* get name */
2017 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
2018
2019 /* parse substatements */
2020 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2021 switch (child->kw) {
2022 case LY_STMT_CONFIG:
2023 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
2024 break;
2025 case LY_STMT_DEFAULT:
2026 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 +01002027 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002028 break;
2029 case LY_STMT_DESCRIPTION:
2030 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
2031 break;
2032 case LY_STMT_IF_FEATURE:
2033 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
2034 break;
2035 case LY_STMT_MANDATORY:
2036 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
2037 break;
2038 case LY_STMT_MUST:
2039 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
2040 break;
2041 case LY_STMT_REFERENCE:
2042 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
2043 break;
2044 case LY_STMT_STATUS:
2045 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
2046 break;
2047 case LY_STMT_TYPE:
2048 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
2049 break;
2050 case LY_STMT_UNITS:
2051 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
2052 break;
2053 case LY_STMT_WHEN:
2054 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
2055 break;
2056 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002057 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002058 break;
2059 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002060 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002061 return LY_EVALID;
2062 }
2063 }
2064
2065 /* mandatory substatements */
2066 if (!leaf->type.name) {
2067 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
2068 return LY_EVALID;
2069 }
2070
2071 return LY_SUCCESS;
2072}
2073
2074/**
2075 * @brief Parse the max-elements statement.
2076 *
2077 * @param[in] ctx parser context.
2078 * @param[in] stmt Source statement data from the parsed extension instance.
2079 * @param[in,out] max Value to write to.
2080 * @param[in,out] flags Flags to write to.
2081 * @param[in,out] exts Extension instances to add to.
2082 *
2083 * @return LY_ERR values.
2084 */
2085static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002086lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
2087 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002088{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002089 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002090 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002091 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002092
2093 if (*flags & LYS_SET_MAX) {
2094 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
2095 return LY_EVALID;
2096 }
2097 *flags |= LYS_SET_MAX;
2098
2099 /* get value */
2100 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2101 arg_len = strlen(stmt->arg);
2102
2103 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
2104 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
2105 return LY_EVALID;
2106 }
2107
2108 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
2109 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002110 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002111 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002112 if (ptr - stmt->arg != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002113 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
2114 return LY_EVALID;
2115 }
2116 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2117 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
2118 return LY_EVALID;
2119 }
2120
2121 *max = num;
2122 } else {
2123 /* unbounded */
2124 *max = 0;
2125 }
2126
2127 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2128 switch (child->kw) {
2129 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002130 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002131 break;
2132 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002133 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002134 return LY_EVALID;
2135 }
2136 }
2137
2138 return LY_SUCCESS;
2139}
2140
2141/**
2142 * @brief Parse the min-elements statement.
2143 *
2144 * @param[in] ctx parser context.
2145 * @param[in] stmt Source statement data from the parsed extension instance.
2146 * @param[in,out] min Value to write to.
2147 * @param[in,out] flags Flags to write to.
2148 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002149 * @return LY_ERR values.
2150 */
2151static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002152lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
2153 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002154{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002155 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002156 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002157 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002158
2159 if (*flags & LYS_SET_MIN) {
2160 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
2161 return LY_EVALID;
2162 }
2163 *flags |= LYS_SET_MIN;
2164
2165 /* get value */
2166 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2167 arg_len = strlen(stmt->arg);
2168
2169 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
2170 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2171 return LY_EVALID;
2172 }
2173
2174 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002175 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002176 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002177 if (ptr - stmt->arg != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002178 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2179 return LY_EVALID;
2180 }
2181 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2182 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
2183 return LY_EVALID;
2184 }
2185 *min = num;
2186
2187 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2188 switch (child->kw) {
2189 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002190 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002191 break;
2192 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002193 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002194 return LY_EVALID;
2195 }
2196 }
2197
2198 return LY_SUCCESS;
2199}
2200
2201/**
2202 * @brief Parse the ordered-by statement.
2203 *
2204 * @param[in] ctx parser context.
2205 * @param[in] stmt Source statement data from the parsed extension instance.
2206 * @param[in,out] flags Flags to write to.
2207 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002208 * @return LY_ERR values.
2209 */
2210static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002211lysp_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 +01002212{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002213 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002214
2215 if (*flags & LYS_ORDBY_MASK) {
2216 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2217 return LY_EVALID;
2218 }
2219
2220 /* get value */
2221 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2222 arg_len = strlen(stmt->arg);
2223 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2224 *flags |= LYS_MAND_TRUE;
2225 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2226 *flags |= LYS_MAND_FALSE;
2227 } else {
2228 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2229 return LY_EVALID;
2230 }
2231
2232 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2233 switch (child->kw) {
2234 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002235 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002236 break;
2237 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002238 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002239 return LY_EVALID;
2240 }
2241 }
2242
2243 return LY_SUCCESS;
2244}
2245
2246/**
2247 * @brief Parse the leaf-list statement.
2248 *
2249 * @param[in] ctx parser context.
2250 * @param[in] stmt Source statement data from the parsed extension instance.
2251 * @param[in] parent Parent node to connect to (not into).
2252 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002253 * @return LY_ERR values.
2254 */
2255static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002256lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002257 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002258{
2259 struct lysp_node_leaflist *llist;
2260
2261 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2262
2263 /* create new leaf-list structure */
2264 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2265 llist->nodetype = LYS_LEAFLIST;
2266 llist->parent = parent;
2267
2268 /* get name */
2269 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2270
2271 /* parse substatements */
2272 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2273 switch (child->kw) {
2274 case LY_STMT_CONFIG:
2275 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2276 break;
2277 case LY_STMT_DEFAULT:
2278 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2279 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2280 break;
2281 case LY_STMT_DESCRIPTION:
2282 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2283 break;
2284 case LY_STMT_IF_FEATURE:
2285 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2286 break;
2287 case LY_STMT_MAX_ELEMENTS:
2288 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2289 break;
2290 case LY_STMT_MIN_ELEMENTS:
2291 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2292 break;
2293 case LY_STMT_MUST:
2294 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2295 break;
2296 case LY_STMT_ORDERED_BY:
2297 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2298 break;
2299 case LY_STMT_REFERENCE:
2300 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2301 break;
2302 case LY_STMT_STATUS:
2303 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2304 break;
2305 case LY_STMT_TYPE:
2306 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2307 break;
2308 case LY_STMT_UNITS:
2309 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2310 break;
2311 case LY_STMT_WHEN:
2312 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2313 break;
2314 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002315 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002316 break;
2317 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002318 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002319 return LY_EVALID;
2320 }
2321 }
2322
2323 /* mandatory substatements */
2324 if (!llist->type.name) {
2325 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2326 return LY_EVALID;
2327 }
2328
2329 return LY_SUCCESS;
2330}
2331
2332/**
2333 * @brief Parse the refine statement.
2334 *
2335 * @param[in] ctx parser context.
2336 * @param[in] stmt Source statement data from the parsed extension instance.
2337 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002338 * @return LY_ERR values.
2339 */
2340static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002341lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002342{
2343 struct lysp_refine *rf;
2344
2345 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2346
2347 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2348
2349 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2350
2351 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2352 switch (child->kw) {
2353 case LY_STMT_CONFIG:
2354 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2355 break;
2356 case LY_STMT_DEFAULT:
2357 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2358 break;
2359 case LY_STMT_DESCRIPTION:
2360 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2361 break;
2362 case LY_STMT_IF_FEATURE:
2363 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2364 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2365 break;
2366 case LY_STMT_MAX_ELEMENTS:
2367 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2368 break;
2369 case LY_STMT_MIN_ELEMENTS:
2370 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2371 break;
2372 case LY_STMT_MUST:
2373 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2374 break;
2375 case LY_STMT_MANDATORY:
2376 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2377 break;
2378 case LY_STMT_REFERENCE:
2379 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2380 break;
2381 case LY_STMT_PRESENCE:
2382 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2383 break;
2384 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002385 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002386 break;
2387 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002388 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002389 return LY_EVALID;
2390 }
2391 }
2392
2393 return LY_SUCCESS;
2394}
2395
2396/**
2397 * @brief Parse the typedef statement.
2398 *
2399 * @param[in] ctx parser context.
2400 * @param[in] stmt Source statement data from the parsed extension instance.
2401 * @param[in] parent Parent node to connect to (not into).
2402 * @param[in,out] typedefs Typedefs to add to.
2403 *
2404 * @return LY_ERR values.
2405 */
2406static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002407lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002408 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002409{
2410 struct lysp_tpdf *tpdf;
2411
2412 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2413
2414 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2415
2416 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2417
2418 /* parse substatements */
2419 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2420 switch (child->kw) {
2421 case LY_STMT_DEFAULT:
2422 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 +01002423 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002424 break;
2425 case LY_STMT_DESCRIPTION:
2426 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2427 break;
2428 case LY_STMT_REFERENCE:
2429 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2430 break;
2431 case LY_STMT_STATUS:
2432 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2433 break;
2434 case LY_STMT_TYPE:
2435 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2436 break;
2437 case LY_STMT_UNITS:
2438 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2439 break;
2440 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002441 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002442 break;
2443 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002444 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002445 return LY_EVALID;
2446 }
2447 }
2448
2449 /* mandatory substatements */
2450 if (!tpdf->type.name) {
2451 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2452 return LY_EVALID;
2453 }
2454
2455 /* store data for collision check */
2456 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2457 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2458 }
2459
2460 return LY_SUCCESS;
2461}
2462
2463/**
2464 * @brief Parse the input or output statement.
2465 *
2466 * @param[in] ctx parser context.
2467 * @param[in] stmt Source statement data from the parsed extension instance.
2468 * @param[in] parent Parent node to connect to (not into).
2469 * @param[in,out] inout_p Input/output pointer to write to.
2470 *
2471 * @return LY_ERR values.
2472 */
2473static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002474lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002475 struct lysp_node_action_inout *inout_p)
2476{
2477 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002478 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002479 return LY_EVALID;
2480 }
2481
2482 /* initiate structure */
2483 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2484 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2485 inout_p->parent = parent;
2486
2487 /* parse substatements */
2488 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2489 switch (child->kw) {
2490 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002491 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002492 /* fall through */
2493 case LY_STMT_ANYXML:
2494 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2495 break;
2496 case LY_STMT_CHOICE:
2497 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2498 break;
2499 case LY_STMT_CONTAINER:
2500 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2501 break;
2502 case LY_STMT_LEAF:
2503 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2504 break;
2505 case LY_STMT_LEAF_LIST:
2506 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2507 break;
2508 case LY_STMT_LIST:
2509 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2510 break;
2511 case LY_STMT_USES:
2512 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2513 break;
2514 case LY_STMT_TYPEDEF:
2515 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2516 break;
2517 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002518 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002519 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2520 break;
2521 case LY_STMT_GROUPING:
2522 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2523 break;
2524 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002525 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002526 break;
2527 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002528 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002529 return LY_EVALID;
2530 }
2531 }
2532
2533 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002534 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002535 return LY_EVALID;
2536 }
2537
2538 return LY_SUCCESS;
2539}
2540
2541/**
2542 * @brief Parse the action statement.
2543 *
2544 * @param[in] ctx parser context.
2545 * @param[in] stmt Source statement data from the parsed extension instance.
2546 * @param[in] parent Parent node to connect to (not into).
2547 * @param[in,out] actions Actions to add to.
2548 *
2549 * @return LY_ERR values.
2550 */
2551static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002552lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002553 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002554{
2555 struct lysp_node_action *act;
2556
2557 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2558
2559 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2560
2561 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2562 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2563 act->parent = parent;
2564
2565 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2566 switch (child->kw) {
2567 case LY_STMT_DESCRIPTION:
2568 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2569 break;
2570 case LY_STMT_IF_FEATURE:
2571 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2572 break;
2573 case LY_STMT_REFERENCE:
2574 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2575 break;
2576 case LY_STMT_STATUS:
2577 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2578 break;
2579
2580 case LY_STMT_INPUT:
2581 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2582 break;
2583 case LY_STMT_OUTPUT:
2584 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2585 break;
2586
2587 case LY_STMT_TYPEDEF:
2588 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2589 break;
2590 case LY_STMT_GROUPING:
2591 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2592 break;
2593 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002594 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 +01002595 break;
2596 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002597 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002598 return LY_EVALID;
2599 }
2600 }
2601
2602 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2603 if (!act->input.nodetype) {
2604 act->input.nodetype = LYS_INPUT;
2605 act->input.parent = &act->node;
2606 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2607 }
2608 if (!act->output.nodetype) {
2609 act->output.nodetype = LYS_OUTPUT;
2610 act->output.parent = &act->node;
2611 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2612 }
2613
2614 return LY_SUCCESS;
2615}
2616
2617/**
2618 * @brief Parse the notification statement.
2619 *
2620 * @param[in] ctx parser context.
2621 * @param[in] stmt Source statement data from the parsed extension instance.
2622 * @param[in] parent Parent node to connect to (not into).
2623 * @param[in,out] notifs Notifications to add to.
2624 *
2625 * @return LY_ERR values.
2626 */
2627static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002628lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002629 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002630{
2631 struct lysp_node_notif *notif;
2632
2633 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2634
2635 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2636
2637 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2638 notif->nodetype = LYS_NOTIF;
2639 notif->parent = parent;
2640
2641 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2642 switch (child->kw) {
2643 case LY_STMT_DESCRIPTION:
2644 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2645 break;
2646 case LY_STMT_IF_FEATURE:
2647 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2648 break;
2649 case LY_STMT_REFERENCE:
2650 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2651 break;
2652 case LY_STMT_STATUS:
2653 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2654 break;
2655
2656 case LY_STMT_ANYDATA:
2657 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2658 /* fall through */
2659 case LY_STMT_ANYXML:
2660 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2661 break;
2662 case LY_STMT_CHOICE:
2663 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2664 break;
2665 case LY_STMT_CONTAINER:
2666 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2667 break;
2668 case LY_STMT_LEAF:
2669 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2670 break;
2671 case LY_STMT_LEAF_LIST:
2672 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2673 break;
2674 case LY_STMT_LIST:
2675 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2676 break;
2677 case LY_STMT_USES:
2678 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2679 break;
2680
2681 case LY_STMT_MUST:
2682 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2683 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2684 break;
2685 case LY_STMT_TYPEDEF:
2686 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2687 break;
2688 case LY_STMT_GROUPING:
2689 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2690 break;
2691 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002692 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002693 break;
2694 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002695 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002696 return LY_EVALID;
2697 }
2698 }
2699
2700 return LY_SUCCESS;
2701}
2702
2703/**
2704 * @brief Parse the grouping statement.
2705 *
2706 * @param[in] ctx parser context.
2707 * @param[in] stmt Source statement data from the parsed extension instance.
2708 * @param[in] parent Parent node to connect to (not into).
2709 * @param[in,out] groupings Groupings to add to.
2710 *
2711 * @return LY_ERR values.
2712 */
2713static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002714lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002715 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002716{
2717 struct lysp_node_grp *grp;
2718
2719 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2720
2721 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2722
2723 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2724 grp->nodetype = LYS_GROUPING;
2725 grp->parent = parent;
2726
2727 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2728 switch (child->kw) {
2729 case LY_STMT_DESCRIPTION:
2730 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2731 break;
2732 case LY_STMT_REFERENCE:
2733 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2734 break;
2735 case LY_STMT_STATUS:
2736 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2737 break;
2738
2739 case LY_STMT_ANYDATA:
2740 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2741 /* fall through */
2742 case LY_STMT_ANYXML:
2743 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2744 break;
2745 case LY_STMT_CHOICE:
2746 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2747 break;
2748 case LY_STMT_CONTAINER:
2749 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2750 break;
2751 case LY_STMT_LEAF:
2752 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2753 break;
2754 case LY_STMT_LEAF_LIST:
2755 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2756 break;
2757 case LY_STMT_LIST:
2758 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2759 break;
2760 case LY_STMT_USES:
2761 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2762 break;
2763
2764 case LY_STMT_TYPEDEF:
2765 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2766 break;
2767 case LY_STMT_ACTION:
2768 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2769 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2770 break;
2771 case LY_STMT_GROUPING:
2772 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2773 break;
2774 case LY_STMT_NOTIFICATION:
2775 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2776 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2777 break;
2778 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002779 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002780 break;
2781 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002782 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002783 return LY_EVALID;
2784 }
2785 }
2786
2787 return LY_SUCCESS;
2788}
2789
2790/**
2791 * @brief Parse the augment statement.
2792 *
2793 * @param[in] ctx parser context.
2794 * @param[in] stmt Source statement data from the parsed extension instance.
2795 * @param[in] parent Parent node to connect to (not into).
2796 * @param[in,out] augments Augments to add to.
2797 *
2798 * @return LY_ERR values.
2799 */
2800static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002801lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002802 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002803{
2804 struct lysp_node_augment *aug;
2805
2806 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2807
2808 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2809
2810 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2811 aug->nodetype = LYS_AUGMENT;
2812 aug->parent = parent;
2813
2814 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2815 switch (child->kw) {
2816 case LY_STMT_DESCRIPTION:
2817 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2818 break;
2819 case LY_STMT_IF_FEATURE:
2820 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2821 break;
2822 case LY_STMT_REFERENCE:
2823 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2824 break;
2825 case LY_STMT_STATUS:
2826 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2827 break;
2828 case LY_STMT_WHEN:
2829 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2830 break;
2831
2832 case LY_STMT_ANYDATA:
2833 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2834 /* fall through */
2835 case LY_STMT_ANYXML:
2836 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2837 break;
2838 case LY_STMT_CASE:
2839 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2840 break;
2841 case LY_STMT_CHOICE:
2842 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2843 break;
2844 case LY_STMT_CONTAINER:
2845 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2846 break;
2847 case LY_STMT_LEAF:
2848 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2849 break;
2850 case LY_STMT_LEAF_LIST:
2851 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2852 break;
2853 case LY_STMT_LIST:
2854 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2855 break;
2856 case LY_STMT_USES:
2857 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2858 break;
2859
2860 case LY_STMT_ACTION:
2861 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2862 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2863 break;
2864 case LY_STMT_NOTIFICATION:
2865 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2866 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2867 break;
2868 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002869 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002870 break;
2871 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002872 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002873 return LY_EVALID;
2874 }
2875 }
2876
2877 return LY_SUCCESS;
2878}
2879
2880/**
2881 * @brief Parse the uses statement.
2882 *
2883 * @param[in] ctx parser context.
2884 * @param[in] stmt Source statement data from the parsed extension instance.
2885 * @param[in] parent Parent node to connect to (not into).
2886 * @param[in,out] siblings Siblings to add to.
2887 *
2888 * @return LY_ERR values.
2889 */
2890static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002891lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002892 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002893{
2894 struct lysp_node_uses *uses;
2895
2896 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2897
2898 /* create uses structure */
2899 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2900
2901 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2902 uses->nodetype = LYS_USES;
2903 uses->parent = parent;
2904
2905 /* parse substatements */
2906 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2907 switch (child->kw) {
2908 case LY_STMT_DESCRIPTION:
2909 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2910 break;
2911 case LY_STMT_IF_FEATURE:
2912 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2913 break;
2914 case LY_STMT_REFERENCE:
2915 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2916 break;
2917 case LY_STMT_STATUS:
2918 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2919 break;
2920 case LY_STMT_WHEN:
2921 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2922 break;
2923
2924 case LY_STMT_REFINE:
2925 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2926 break;
2927 case LY_STMT_AUGMENT:
2928 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2929 break;
2930 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002931 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002932 break;
2933 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002934 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002935 return LY_EVALID;
2936 }
2937 }
2938
2939 return LY_SUCCESS;
2940}
2941
2942/**
2943 * @brief Parse the case statement.
2944 *
2945 * @param[in] ctx parser context.
2946 * @param[in] stmt Source statement data from the parsed extension instance.
2947 * @param[in] parent Parent node to connect to (not into).
2948 * @param[in,out] siblings Siblings to add to.
2949 *
2950 * @return LY_ERR values.
2951 */
2952static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002953lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002954 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002955{
2956 struct lysp_node_case *cas;
2957
2958 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2959
2960 /* create new case structure */
2961 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2962
2963 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2964 cas->nodetype = LYS_CASE;
2965 cas->parent = parent;
2966
2967 /* parse substatements */
2968 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2969 switch (child->kw) {
2970 case LY_STMT_DESCRIPTION:
2971 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2972 break;
2973 case LY_STMT_IF_FEATURE:
2974 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2975 break;
2976 case LY_STMT_REFERENCE:
2977 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2978 break;
2979 case LY_STMT_STATUS:
2980 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2981 break;
2982 case LY_STMT_WHEN:
2983 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2984 break;
2985
2986 case LY_STMT_ANYDATA:
2987 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2988 /* fall through */
2989 case LY_STMT_ANYXML:
2990 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2991 break;
2992 case LY_STMT_CHOICE:
2993 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2994 break;
2995 case LY_STMT_CONTAINER:
2996 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2997 break;
2998 case LY_STMT_LEAF:
2999 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
3000 break;
3001 case LY_STMT_LEAF_LIST:
3002 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
3003 break;
3004 case LY_STMT_LIST:
3005 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
3006 break;
3007 case LY_STMT_USES:
3008 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
3009 break;
3010 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003011 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003012 break;
3013 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003014 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003015 return LY_EVALID;
3016 }
3017 }
3018 return LY_SUCCESS;
3019}
3020
3021/**
3022 * @brief Parse the choice statement.
3023 *
3024 * @param[in] ctx parser context.
3025 * @param[in] stmt Source statement data from the parsed extension instance.
3026 * @param[in] parent Parent node to connect to (not into).
3027 * @param[in,out] siblings Siblings to add to.
3028 *
3029 * @return LY_ERR values.
3030 */
3031static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003032lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003033 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003034{
3035 struct lysp_node_choice *choice;
3036
3037 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3038
3039 /* create new choice structure */
3040 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
3041
3042 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
3043 choice->nodetype = LYS_CHOICE;
3044 choice->parent = parent;
3045
3046 /* parse substatements */
3047 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3048 switch (child->kw) {
3049 case LY_STMT_CONFIG:
3050 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
3051 break;
3052 case LY_STMT_DESCRIPTION:
3053 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
3054 break;
3055 case LY_STMT_IF_FEATURE:
3056 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
3057 break;
3058 case LY_STMT_MANDATORY:
3059 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
3060 break;
3061 case LY_STMT_REFERENCE:
3062 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
3063 break;
3064 case LY_STMT_STATUS:
3065 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
3066 break;
3067 case LY_STMT_WHEN:
3068 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
3069 break;
3070 case LY_STMT_DEFAULT:
3071 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 +01003072 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003073 break;
3074 case LY_STMT_ANYDATA:
3075 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
3076 /* fall through */
3077 case LY_STMT_ANYXML:
3078 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
3079 break;
3080 case LY_STMT_CASE:
3081 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
3082 break;
3083 case LY_STMT_CHOICE:
3084 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
3085 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
3086 break;
3087 case LY_STMT_CONTAINER:
3088 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
3089 break;
3090 case LY_STMT_LEAF:
3091 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
3092 break;
3093 case LY_STMT_LEAF_LIST:
3094 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
3095 break;
3096 case LY_STMT_LIST:
3097 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
3098 break;
3099 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003100 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003101 break;
3102 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003103 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003104 return LY_EVALID;
3105 }
3106 }
3107 return LY_SUCCESS;
3108}
3109
3110/**
3111 * @brief Parse the container statement.
3112 *
3113 * @param[in] ctx parser context.
3114 * @param[in] stmt Source statement data from the parsed extension instance.
3115 * @param[in] parent Parent node to connect to (not into).
3116 * @param[in,out] siblings Siblings to add to.
3117 *
3118 * @return LY_ERR values.
3119 */
3120static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003121lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003122 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003123{
3124 struct lysp_node_container *cont;
3125
3126 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3127
3128 /* create new container structure */
3129 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
3130
3131 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
3132 cont->nodetype = LYS_CONTAINER;
3133 cont->parent = parent;
3134
3135 /* parse substatements */
3136 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3137 switch (child->kw) {
3138 case LY_STMT_CONFIG:
3139 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
3140 break;
3141 case LY_STMT_DESCRIPTION:
3142 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
3143 break;
3144 case LY_STMT_IF_FEATURE:
3145 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
3146 break;
3147 case LY_STMT_REFERENCE:
3148 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
3149 break;
3150 case LY_STMT_STATUS:
3151 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
3152 break;
3153 case LY_STMT_WHEN:
3154 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
3155 break;
3156 case LY_STMT_PRESENCE:
3157 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
3158 break;
3159 case LY_STMT_ANYDATA:
3160 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
3161 /* fall through */
3162 case LY_STMT_ANYXML:
3163 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
3164 break;
3165 case LY_STMT_CHOICE:
3166 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
3167 break;
3168 case LY_STMT_CONTAINER:
3169 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
3170 break;
3171 case LY_STMT_LEAF:
3172 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
3173 break;
3174 case LY_STMT_LEAF_LIST:
3175 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
3176 break;
3177 case LY_STMT_LIST:
3178 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
3179 break;
3180 case LY_STMT_USES:
3181 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
3182 break;
3183
3184 case LY_STMT_TYPEDEF:
3185 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
3186 break;
3187 case LY_STMT_MUST:
3188 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
3189 break;
3190 case LY_STMT_ACTION:
3191 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
3192 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
3193 break;
3194 case LY_STMT_GROUPING:
3195 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3196 break;
3197 case LY_STMT_NOTIFICATION:
3198 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3199 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3200 break;
3201 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003202 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003203 break;
3204 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003205 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003206 return LY_EVALID;
3207 }
3208 }
3209
3210 return LY_SUCCESS;
3211}
3212
3213/**
3214 * @brief Parse the list statement.
3215 *
3216 * @param[in] ctx parser context.
3217 * @param[in] stmt Source statement data from the parsed extension instance.
3218 * @param[in] parent Parent node to connect to (not into).
3219 * @param[in,out] siblings Siblings to add to.
3220 *
3221 * @return LY_ERR values.
3222 */
3223static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003224lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003225 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003226{
3227 struct lysp_node_list *list;
3228
3229 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3230
3231 /* create new list structure */
3232 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3233
3234 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3235 list->nodetype = LYS_LIST;
3236 list->parent = parent;
3237
3238 /* parse substatements */
3239 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3240 switch (child->kw) {
3241 case LY_STMT_CONFIG:
3242 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3243 break;
3244 case LY_STMT_DESCRIPTION:
3245 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3246 break;
3247 case LY_STMT_IF_FEATURE:
3248 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3249 break;
3250 case LY_STMT_REFERENCE:
3251 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3252 break;
3253 case LY_STMT_STATUS:
3254 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3255 break;
3256 case LY_STMT_WHEN:
3257 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3258 break;
3259 case LY_STMT_KEY:
3260 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3261 break;
3262 case LY_STMT_MAX_ELEMENTS:
3263 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3264 break;
3265 case LY_STMT_MIN_ELEMENTS:
3266 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3267 break;
3268 case LY_STMT_ORDERED_BY:
3269 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3270 break;
3271 case LY_STMT_UNIQUE:
3272 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3273 break;
3274
3275 case LY_STMT_ANYDATA:
3276 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3277 /* fall through */
3278 case LY_STMT_ANYXML:
3279 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3280 break;
3281 case LY_STMT_CHOICE:
3282 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3283 break;
3284 case LY_STMT_CONTAINER:
3285 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3286 break;
3287 case LY_STMT_LEAF:
3288 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3289 break;
3290 case LY_STMT_LEAF_LIST:
3291 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3292 break;
3293 case LY_STMT_LIST:
3294 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3295 break;
3296 case LY_STMT_USES:
3297 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3298 break;
3299
3300 case LY_STMT_TYPEDEF:
3301 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3302 break;
3303 case LY_STMT_MUST:
3304 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3305 break;
3306 case LY_STMT_ACTION:
3307 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3308 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3309 break;
3310 case LY_STMT_GROUPING:
3311 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3312 break;
3313 case LY_STMT_NOTIFICATION:
3314 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3315 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3316 break;
3317 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003318 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003319 break;
3320 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003321 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003322 return LY_EVALID;
3323 }
3324 }
3325
3326 return LY_SUCCESS;
3327}
3328
Michal Vasko193dacd2022-10-13 08:43:05 +02003329/**
3330 * @brief Parse generic statement structure into a specific parsed-schema structure.
3331 *
3332 * @param[in] pctx Parse context of the @p stmt being processed.
3333 * @param[in] stmt Generic statement structure to process.
3334 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3335 * @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.
3336 * @return LY_ERR value.
3337 */
3338static LY_ERR
3339lysp_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 +02003340{
Radek Krejciad5963b2019-09-06 16:03:05 +02003341 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003342 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003343
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003344 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003345 case LY_STMT_NOTIFICATION:
3346 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3347 break;
3348 case LY_STMT_INPUT:
3349 case LY_STMT_OUTPUT: {
3350 struct lysp_node_action_inout *inout;
3351
3352 *result = inout = calloc(1, sizeof *inout);
3353 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3354 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3355 break;
3356 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003357 case LY_STMT_ACTION:
3358 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003359 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003360 break;
3361 case LY_STMT_ANYDATA:
3362 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003363 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003364 break;
3365 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003366 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003367 break;
3368 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003369 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003370 break;
3371 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003372 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003373 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003374 case LY_STMT_CONTAINER:
3375 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003376 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003377 case LY_STMT_GROUPING:
3378 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3379 break;
3380 case LY_STMT_LEAF:
3381 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3382 break;
3383 case LY_STMT_LEAF_LIST:
3384 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3385 break;
3386 case LY_STMT_LIST:
3387 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3388 break;
3389 case LY_STMT_USES:
3390 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3391 break;
3392 case LY_STMT_BASE:
3393 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3394 break;
3395 case LY_STMT_ARGUMENT:
3396 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003397 case LY_STMT_CONTACT:
3398 case LY_STMT_DESCRIPTION:
3399 case LY_STMT_ERROR_APP_TAG:
3400 case LY_STMT_ERROR_MESSAGE:
3401 case LY_STMT_KEY:
3402 case LY_STMT_NAMESPACE:
3403 case LY_STMT_ORGANIZATION:
3404 case LY_STMT_PRESENCE:
3405 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003406 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003407 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003408 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003409 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003410 case LY_STMT_BIT:
3411 case LY_STMT_ENUM:
3412 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3413 break;
3414 case LY_STMT_CONFIG:
3415 assert(*result);
3416 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003417 break;
3418 case LY_STMT_DEFAULT:
3419 case LY_STMT_IF_FEATURE:
3420 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003421 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3422 break;
3423 case LY_STMT_DEVIATE:
3424 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3425 break;
3426 case LY_STMT_DEVIATION:
3427 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3428 break;
3429 case LY_STMT_EXTENSION:
3430 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003431 break;
3432 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003433 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3434 break;
3435 case LY_STMT_FEATURE:
3436 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003437 break;
3438 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003439 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003440 break;
3441 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003442 case LY_STMT_RANGE: {
3443 struct lysp_restr *restr;
3444
3445 *result = restr = calloc(1, sizeof *restr);
3446 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3447
3448 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003449 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003450 }
3451 case LY_STMT_MUST:
3452 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3453 break;
3454 case LY_STMT_IDENTITY:
3455 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3456 break;
3457 case LY_STMT_IMPORT:
3458 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3459 break;
3460 case LY_STMT_INCLUDE:
3461 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003462 break;
3463 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003464 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003465 break;
3466 case LY_STMT_MAX_ELEMENTS:
3467 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003468 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003469 break;
3470 case LY_STMT_MIN_ELEMENTS:
3471 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003472 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003473 break;
3474 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003475 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003476 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003477 case LY_STMT_MODULE: {
3478 struct lysp_module *mod;
3479
3480 *result = mod = calloc(1, sizeof *mod);
3481 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3482 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003483 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003484 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003485 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003486 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003487 break;
3488 case LY_STMT_PATH: {
3489 const char *str_path = NULL;
3490
Michal Vasko193dacd2022-10-13 08:43:05 +02003491 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3492 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003493 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003494 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003495 break;
3496 }
3497 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003498 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003499 break;
3500 case LY_STMT_POSITION:
3501 case LY_STMT_VALUE:
3502 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003503 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003504 break;
3505 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003506 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003507 break;
3508 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003509 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003510 break;
3511 case LY_STMT_REQUIRE_INSTANCE:
3512 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003513 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3514 break;
3515 case LY_STMT_REVISION:
3516 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003517 break;
Michal Vasko69730152020-10-09 16:30:07 +02003518 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003519 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003520 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003521 case LY_STMT_SUBMODULE: {
3522 struct lysp_submodule *submod;
3523
3524 *result = submod = calloc(1, sizeof *submod);
3525 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3526 ret = lysp_stmt_submodule(pctx, stmt, submod);
3527 break;
3528 }
Radek Krejci335332a2019-09-05 13:03:35 +02003529 case LY_STMT_TYPE: {
3530 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003531
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003532 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003533 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3534 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003535 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003536 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003537 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003538 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003539 break;
3540 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003541 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3542 break;
3543 case LY_STMT_YANG_VERSION:
3544 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3545 break;
3546 case LY_STMT_YIN_ELEMENT:
3547 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003548 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003549 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003550 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003551 return LY_EINT;
3552 }
3553
Radek Krejciad5963b2019-09-06 16:03:05 +02003554 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003555}
Michal Vasko59892dd2022-05-13 11:02:30 +02003556
Michal Vasko193dacd2022-10-13 08:43:05 +02003557LY_ERR
3558lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003559{
Michal Vasko193dacd2022-10-13 08:43:05 +02003560 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003561
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003562 if (!substmt->storage_p) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003563 /* nothing to parse, ignored */
3564 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003565 }
3566
Michal Vasko193dacd2022-10-13 08:43:05 +02003567 switch (stmt->kw) {
3568 case LY_STMT_NOTIFICATION:
3569 case LY_STMT_INPUT:
3570 case LY_STMT_OUTPUT:
3571 case LY_STMT_ACTION:
3572 case LY_STMT_RPC:
3573 case LY_STMT_ANYDATA:
3574 case LY_STMT_ANYXML:
3575 case LY_STMT_AUGMENT:
3576 case LY_STMT_CASE:
3577 case LY_STMT_CHOICE:
3578 case LY_STMT_CONTAINER:
3579 case LY_STMT_GROUPING:
3580 case LY_STMT_LEAF:
3581 case LY_STMT_LEAF_LIST:
3582 case LY_STMT_LIST:
3583 case LY_STMT_USES: {
3584 struct lysp_node **pnodes_p, *pnode = NULL;
3585
3586 /* parse the node */
3587 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3588
3589 /* usually is a linked-list of all the parsed schema nodes */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003590 pnodes_p = (struct lysp_node **)substmt->storage_p;
Michal Vasko193dacd2022-10-13 08:43:05 +02003591 while (*pnodes_p) {
3592 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003593 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003594 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003595
3596 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003597 }
3598 case LY_STMT_BASE:
3599 case LY_STMT_BIT:
3600 case LY_STMT_DEFAULT:
3601 case LY_STMT_DEVIATE:
3602 case LY_STMT_DEVIATION:
3603 case LY_STMT_ENUM:
3604 case LY_STMT_EXTENSION:
3605 case LY_STMT_EXTENSION_INSTANCE:
3606 case LY_STMT_FEATURE:
3607 case LY_STMT_IDENTITY:
3608 case LY_STMT_IF_FEATURE:
3609 case LY_STMT_IMPORT:
3610 case LY_STMT_INCLUDE:
3611 case LY_STMT_MUST:
3612 case LY_STMT_PATTERN:
3613 case LY_STMT_REFINE:
3614 case LY_STMT_REVISION:
3615 case LY_STMT_TYPEDEF:
3616 case LY_STMT_UNIQUE:
3617 /* parse, sized array */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003618 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003619 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003620
3621 case LY_STMT_ARGUMENT:
3622 case LY_STMT_BELONGS_TO:
3623 case LY_STMT_CONTACT:
3624 case LY_STMT_DESCRIPTION:
3625 case LY_STMT_ERROR_APP_TAG:
3626 case LY_STMT_ERROR_MESSAGE:
3627 case LY_STMT_FRACTION_DIGITS:
3628 case LY_STMT_KEY:
3629 case LY_STMT_LENGTH:
3630 case LY_STMT_MANDATORY:
3631 case LY_STMT_MAX_ELEMENTS:
3632 case LY_STMT_MIN_ELEMENTS:
3633 case LY_STMT_MODIFIER:
3634 case LY_STMT_MODULE:
3635 case LY_STMT_NAMESPACE:
3636 case LY_STMT_ORGANIZATION:
3637 case LY_STMT_PATH:
3638 case LY_STMT_POSITION:
3639 case LY_STMT_PREFIX:
3640 case LY_STMT_PRESENCE:
3641 case LY_STMT_RANGE:
3642 case LY_STMT_REFERENCE:
3643 case LY_STMT_REQUIRE_INSTANCE:
3644 case LY_STMT_REVISION_DATE:
3645 case LY_STMT_SUBMODULE:
3646 case LY_STMT_TYPE:
3647 case LY_STMT_UNITS:
3648 case LY_STMT_VALUE:
3649 case LY_STMT_WHEN:
3650 case LY_STMT_YANG_VERSION:
3651 case LY_STMT_YIN_ELEMENT:
3652 /* single item */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003653 if (*substmt->storage_p) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003654 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3655 rc = LY_EVALID;
3656 goto cleanup;
3657 }
3658
3659 /* parse */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003660 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003661 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003662
3663 case LY_STMT_CONFIG:
3664 /* single item */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003665 if ((*(uint16_t *)substmt->storage_p) & LYS_CONFIG_MASK) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003666 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3667 rc = LY_EVALID;
3668 goto cleanup;
3669 }
3670
3671 /* parse */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003672 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +02003673 break;
3674
3675 case LY_STMT_ORDERED_BY:
3676 /* single item */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003677 if ((*(uint16_t *)substmt->storage_p) & LYS_ORDBY_MASK) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003678 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3679 rc = LY_EVALID;
3680 goto cleanup;
3681 }
3682
3683 /* parse */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003684 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +02003685 break;
3686
3687 case LY_STMT_STATUS:
3688 /* single item */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003689 if ((*(uint16_t *)substmt->storage_p) & LYS_STATUS_MASK) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003690 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3691 rc = LY_EVALID;
3692 goto cleanup;
3693 }
3694
3695 /* parse */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003696 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +02003697 break;
3698
Michal Vasko59892dd2022-05-13 11:02:30 +02003699 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003700 LOGINT(PARSER_CTX(pctx));
3701 rc = LY_EINT;
3702 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003703 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003704
3705cleanup:
3706 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003707}