blob: 5dadecfe5660c395aa34491bc21fe69bcedd8d38 [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 Vaskoa7b816d2024-09-10 15:03:56 +02006 * Copyright (c) 2015 - 2024 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);
Michal Vasko0c9a1d32024-09-11 13:53:39 +020073 struct lysc_ctx cctx = {0};
Michal Vaskoa7b816d2024-09-10 15:03:56 +020074 const struct lys_module *mod1, *mod2;
75 const struct lysc_node *schema;
Michal Vasko820efe82023-05-12 15:47:43 +020076 LY_ARRAY_COUNT_TYPE u;
77 struct ly_err_item *err = NULL;
78 struct lysp_type *type_p = NULL;
79 struct lysc_pattern **patterns = NULL;
80 const char *value;
81
Michal Vaskoa7b816d2024-09-10 15:03:56 +020082 /* find the used modules, we will either use a compiled leaf or compile the relevant type ourselves */
83 mod1 = ly_ctx_get_module_implemented(ctx, "notifications");
84 mod2 = ly_ctx_get_module_latest(ctx, "ietf-yang-types");
85 assert(mod2);
Michal Vasko820efe82023-05-12 15:47:43 +020086
Michal Vaskoa7b816d2024-09-10 15:03:56 +020087 if (mod1 || !mod2->parsed) {
88 /* get date-and-time leaf */
89 schema = lys_find_path(LYD_CTX(node), NULL, "/notifications:notification/eventTime", 0);
90 LY_CHECK_RET(!schema, LY_ENOTFOUND);
91
92 /* validate the value */
93 value = lyd_get_value(node);
94 LY_CHECK_RET(lyd_value_validate(LYD_CTX(node), schema, value, strlen(value), NULL, NULL, NULL));
95 } else {
96 LYSC_CTX_INIT_CTX(cctx, ctx);
97
98 /* get date-and-time parsed type */
99 LY_ARRAY_FOR(mod2->parsed->typedefs, u) {
100 if (!strcmp(mod2->parsed->typedefs[u].name, "date-and-time")) {
101 type_p = &mod2->parsed->typedefs[u].type;
102 break;
103 }
Michal Vasko820efe82023-05-12 15:47:43 +0200104 }
Michal Vaskoa7b816d2024-09-10 15:03:56 +0200105 assert(type_p);
106
107 /* compile patterns */
108 assert(type_p->patterns);
109 LY_CHECK_GOTO(rc = lys_compile_type_patterns(&cctx, type_p->patterns, NULL, &patterns), cleanup);
110
111 /* validate */
112 value = lyd_get_value(node);
113 rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err);
Michal Vasko820efe82023-05-12 15:47:43 +0200114 }
Michal Vasko820efe82023-05-12 15:47:43 +0200115
116cleanup:
117 FREE_ARRAY(&cctx.free_ctx, patterns, lysc_pattern_free);
118 if (rc && err) {
Michal Vasko7a266772024-01-23 11:02:38 +0100119 ly_err_print(ctx, err);
Michal Vasko820efe82023-05-12 15:47:43 +0200120 ly_err_free(err);
121 LOGVAL(ctx, LYVE_DATA, "Invalid \"eventTime\" in the notification.");
122 }
123 return rc;
124}
125
126LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +0200127lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op)
128{
129 const struct lyd_node *iter;
130
131 *op = NULL;
132
133 if (!parent) {
134 /* no parent, nothing to look for */
135 return LY_SUCCESS;
136 }
137
138 /* we need to find the operation node if it already exists */
139 for (iter = parent; iter; iter = lyd_parent(iter)) {
140 if (iter->schema && (iter->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
141 break;
142 }
143 }
144
145 if (!iter) {
146 /* no operation found */
147 return LY_SUCCESS;
148 }
149
Michal Vaskoe3ed7dc2022-11-30 11:39:44 +0100150 if (!(int_opts & LYD_INTOPT_ANY)) {
151 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
152 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
153 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
154 return LY_EINVAL;
155 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
156 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
157 iter->schema->name);
158 return LY_EINVAL;
159 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
160 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
161 iter->schema->name);
162 return LY_EINVAL;
163 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
164 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
165 iter->schema->name);
166 return LY_EINVAL;
167 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200168 }
169
170 *op = (struct lyd_node *)iter;
171 return LY_SUCCESS;
172}
173
Michal Vaskoa878a892023-08-18 12:22:07 +0200174const struct lysc_node *
175lyd_parser_node_schema(const struct lyd_node *node)
176{
177 uint32_t i;
178 const struct lyd_node *iter;
179 const struct lysc_node *schema = NULL;
180 const struct lys_module *mod;
181
182 if (!node) {
183 return NULL;
184 } else if (node->schema) {
185 /* simplest case */
186 return node->schema;
187 }
188
189 /* find the first schema node in the parsed nodes */
190 i = ly_log_location_dnode_count();
191 if (i) {
192 do {
193 --i;
194 if (ly_log_location_dnode(i)->schema) {
195 /* this node is processed */
196 schema = ly_log_location_dnode(i)->schema;
197 ++i;
198 break;
199 }
200 } while (i);
201 }
202
203 /* get schema node of an opaque node */
204 do {
205 /* get next data node */
206 if (i == ly_log_location_dnode_count()) {
207 iter = node;
208 } else {
209 iter = ly_log_location_dnode(i);
210 }
211 assert(!iter->schema);
212
213 /* get module */
Michal Vasko420cc252023-08-24 08:14:24 +0200214 mod = lyd_node_module(iter);
Michal Vaskoa878a892023-08-18 12:22:07 +0200215 if (!mod) {
216 /* unknown module, no schema node */
217 schema = NULL;
218 break;
219 }
220
221 /* get schema node */
222 schema = lys_find_child(schema, mod, LYD_NAME(iter), 0, 0, 0);
223
224 /* move to the descendant */
225 ++i;
226 } while (schema && (iter != node));
227
228 return schema;
229}
230
Michal Vasko59892dd2022-05-13 11:02:30 +0200231LY_ERR
232lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
233{
234 LY_ERR rc = LY_SUCCESS;
235
Michal Vasko7a266772024-01-23 11:02:38 +0100236 LOG_LOCSET(snode, NULL);
Michal Vasko59892dd2022-05-13 11:02:30 +0200237
238 if (lydctx->int_opts & LYD_INTOPT_ANY) {
239 /* nothing to check, everything is allowed */
240 goto cleanup;
241 }
242
243 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
244 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
245 rc = LY_EVALID;
246 goto cleanup;
247 }
248
249 if (snode->nodetype == LYS_RPC) {
250 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
251 if (lydctx->op_node) {
252 goto error_node_dup;
253 }
254 } else {
255 goto error_node_inval;
256 }
257 } else if (snode->nodetype == LYS_ACTION) {
258 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
259 if (lydctx->op_node) {
260 goto error_node_dup;
261 }
262 } else {
263 goto error_node_inval;
264 }
265 } else if (snode->nodetype == LYS_NOTIF) {
266 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
267 if (lydctx->op_node) {
268 goto error_node_dup;
269 }
270 } else {
271 goto error_node_inval;
272 }
273 }
274
275 /* success */
276 goto cleanup;
277
278error_node_dup:
279 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
280 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
281 lydctx->op_node->schema->name);
282 rc = LY_EVALID;
283 goto cleanup;
284
285error_node_inval:
286 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
287 snode->name);
288 rc = LY_EVALID;
289
290cleanup:
Michal Vasko7a266772024-01-23 11:02:38 +0100291 LOG_LOCBACK(1, 0);
Michal Vasko59892dd2022-05-13 11:02:30 +0200292 return rc;
293}
294
295LY_ERR
296lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
297 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
298{
Michal Vasko9dbb91d2023-01-30 13:59:22 +0100299 LY_ERR r;
Michal Vasko59892dd2022-05-13 11:02:30 +0200300 ly_bool incomplete;
Michal Vaskoa5c4fa42024-02-26 14:04:00 +0100301 ly_bool store_only = (lydctx->parse_opts & LYD_PARSE_STORE_ONLY) == LYD_PARSE_STORE_ONLY ? 1 : 0;
Michal Vasko59892dd2022-05-13 11:02:30 +0200302
stewegd4cde642024-02-21 08:34:16 +0100303 if ((r = lyd_create_term(schema, value, value_len, 1, store_only, dynamic, format, prefix_data,
304 hints, &incomplete, node))) {
Michal Vasko9dbb91d2023-01-30 13:59:22 +0100305 if (lydctx->data_ctx->ctx != schema->module->ctx) {
306 /* move errors to the main context */
307 ly_err_move(schema->module->ctx, (struct ly_ctx *)lydctx->data_ctx->ctx);
308 }
309 return r;
310 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200311
312 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
313 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
314 }
315 return LY_SUCCESS;
316}
317
318LY_ERR
319lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
320 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
321 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
322{
Michal Vaskodd03ff12023-09-11 10:30:48 +0200323 LY_ERR rc = LY_SUCCESS;
324 char *dpath = NULL, *path = NULL;
Michal Vasko59892dd2022-05-13 11:02:30 +0200325 ly_bool incomplete;
326 struct lyd_meta *first = NULL;
Michal Vaskoa5c4fa42024-02-26 14:04:00 +0100327 ly_bool store_only = (lydctx->parse_opts & LYD_PARSE_STORE_ONLY) == LYD_PARSE_STORE_ONLY ? 1 : 0;
Michal Vasko59892dd2022-05-13 11:02:30 +0200328
329 if (meta && *meta) {
330 /* remember the first metadata */
331 first = *meta;
332 }
333
Michal Vaskodd03ff12023-09-11 10:30:48 +0200334 /* generate path to the metadata */
335 LY_CHECK_RET(ly_vlog_build_data_path(lydctx->data_ctx->ctx, &dpath));
336 if (asprintf(&path, "%s/@%s:%.*s", dpath, mod->name, (int)name_len, name) == -1) {
337 LOGMEM(lydctx->data_ctx->ctx);
338 rc = LY_EMEM;
339 goto cleanup;
340 }
Michal Vasko7a266772024-01-23 11:02:38 +0100341 ly_log_location(NULL, NULL, path, NULL);
Michal Vaskodd03ff12023-09-11 10:30:48 +0200342
stewegd4cde642024-02-21 08:34:16 +0100343 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 +0200344 prefix_data, hints, ctx_node, 0, &incomplete), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +0200345
346 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
Michal Vaskodd03ff12023-09-11 10:30:48 +0200347 LY_CHECK_GOTO(rc = ly_set_add(&lydctx->meta_types, *meta, 1, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +0200348 }
349
350 if (first) {
351 /* always return the first metadata */
352 *meta = first;
353 }
354
Michal Vaskodd03ff12023-09-11 10:30:48 +0200355cleanup:
Michal Vasko7a266772024-01-23 11:02:38 +0100356 ly_log_location_revert(0, 0, 1, 0);
Michal Vaskodd03ff12023-09-11 10:30:48 +0200357 free(dpath);
358 free(path);
359 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +0200360}
361
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200362LY_ERR
363lyd_parse_check_keys(struct lyd_node *node)
364{
365 const struct lysc_node *skey = NULL;
366 const struct lyd_node *key;
367
368 assert(node->schema->nodetype == LYS_LIST);
369
370 key = lyd_child(node);
371 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
372 if (!key || (key->schema != skey)) {
373 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
374 return LY_EVALID;
375 }
376
377 key = key->next;
378 }
379
380 return LY_SUCCESS;
381}
382
383LY_ERR
384lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
385 struct lysc_ext_instance *ext)
386{
aPieceked39cbe2023-11-06 14:20:27 +0100387 struct lyd_meta *meta2, *prev_meta = NULL, *next_meta = NULL;
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200388 struct lyd_ctx_ext_val *ext_val;
389
Michal Vaskobc9f76f2022-12-01 10:31:38 +0100390 if (lydctx->parse_opts & LYD_PARSE_NO_NEW) {
391 node->flags &= ~LYD_NEW;
392 }
393
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200394 if (lysc_has_when(node->schema)) {
Michal Vaskofbb48c22022-11-30 13:28:03 +0100395 if (lydctx->parse_opts & LYD_PARSE_WHEN_TRUE) {
396 /* the condition was true before */
397 node->flags |= LYD_WHEN_TRUE;
398 }
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200399 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
400 /* remember we need to evaluate this node's when */
401 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
402 }
403 }
404
405 LY_LIST_FOR(*meta, meta2) {
406 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
407 meta2->value.boolean) {
408 /* node is default according to the metadata */
409 node->flags |= LYD_DEFAULT;
410
aPieceked39cbe2023-11-06 14:20:27 +0100411 next_meta = meta2->next;
412
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200413 /* delete the metadata */
aPieceked39cbe2023-11-06 14:20:27 +0100414 if (meta != &node->meta) {
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200415 *meta = (*meta)->next;
416 }
417 lyd_free_meta_single(meta2);
aPieceked39cbe2023-11-06 14:20:27 +0100418 if (prev_meta) {
419 prev_meta->next = next_meta;
420 }
Michal Vasko4754d4a2022-12-01 10:11:21 +0100421
422 /* update dflt flag for all parent NP containers */
423 lyd_cont_set_dflt(lyd_parent(node));
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200424 break;
425 }
426
427 prev_meta = meta2;
428 }
429
430 if (ext) {
431 /* parsed for an extension */
432 node->flags |= LYD_EXT;
433
434 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
435 /* rememeber for validation */
436 ext_val = malloc(sizeof *ext_val);
437 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
438 ext_val->ext = ext;
439 ext_val->sibling = node;
440 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
441 }
442 }
443
444 return LY_SUCCESS;
445}
446
Michal Vasko193dacd2022-10-13 08:43:05 +0200447void
448lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
449{
450 char path[PATH_MAX];
451
452#ifndef __APPLE__
453 char proc_path[32];
454 int len;
455#endif
456
457 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
458 if (*filepath) {
459 /* filepath already set */
460 return;
461 }
462
463 switch (in->type) {
464 case LY_IN_FILEPATH:
465 if (realpath(in->method.fpath.filepath, path) != NULL) {
466 lydict_insert(ctx, path, 0, filepath);
467 } else {
468 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
469 }
470
471 break;
472 case LY_IN_FD:
473#ifdef __APPLE__
474 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
475 lydict_insert(ctx, path, 0, filepath);
476 }
477#elif defined _WIN32
478 HANDLE h = _get_osfhandle(in->method.fd);
479 FILE_NAME_INFO info;
Michal Vasko2bf4af42023-01-04 12:08:38 +0100480
Michal Vasko193dacd2022-10-13 08:43:05 +0200481 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
482 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
Michal Vasko2bf4af42023-01-04 12:08:38 +0100483
Michal Vasko193dacd2022-10-13 08:43:05 +0200484 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
485 lydict_insert(ctx, buf, len, filepath);
486 }
487#else
488 /* get URI if there is /proc */
489 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
490 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
491 lydict_insert(ctx, path, len, filepath);
492 }
493#endif
494 break;
495 case LY_IN_MEMORY:
496 case LY_IN_FILE:
497 /* nothing to do */
498 break;
499 default:
500 LOGINT(ctx);
501 break;
502 }
503}
504
Michal Vaskod0625d72022-10-06 15:02:50 +0200505static 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 +0100506 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200507static 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 +0100508 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200509static 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 +0100510 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200511static 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 +0100512 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200513static 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 +0100514 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200515static 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 +0100516 struct lysp_node **siblings);
517
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100518/**
519 * @brief Validate stmt string value.
520 *
521 * @param[in] ctx Parser context.
522 * @param[in] val_type String value type.
523 * @param[in] val Value to validate.
524 * @return LY_ERR value.
525 */
Radek Krejci335332a2019-09-05 13:03:35 +0200526static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200527lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200528{
Radek Krejci857189e2020-09-01 13:26:36 +0200529 uint8_t prefix = 0;
530 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200531 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200532 size_t utf8_char_len;
533
Michal Vaskocfa1a962023-02-27 09:28:45 +0100534 if (!val) {
535 if (val_type == Y_MAYBE_STR_ARG) {
536 /* fine */
537 return LY_SUCCESS;
538 }
539
540 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Missing an expected string.");
541 return LY_EVALID;
542 }
543
Radek Krejci335332a2019-09-05 13:03:35 +0200544 while (*val) {
545 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200546 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200547
548 switch (val_type) {
549 case Y_IDENTIF_ARG:
550 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
551 break;
552 case Y_PREF_IDENTIF_ARG:
553 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
554 break;
555 case Y_STR_ARG:
556 case Y_MAYBE_STR_ARG:
557 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
558 break;
559 }
560 first = 0;
561 }
562
563 return LY_SUCCESS;
564}
565
566/**
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100567 * @brief Duplicate statement siblings, recursively.
568 *
569 * @param[in] ctx Parser context.
570 * @param[in] stmt Statement to duplicate.
571 * @param[out] first First duplicated statement, the rest follow.
572 * @return LY_ERR value.
573 */
574static LY_ERR
575lysp_stmt_dup(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_stmt **first)
576{
577 struct lysp_stmt *child, *last = NULL;
578
579 LY_LIST_FOR(stmt, stmt) {
580 child = calloc(1, sizeof *child);
581 LY_CHECK_ERR_RET(!child, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
582
583 if (last) {
584 last->next = child;
585 } else {
586 assert(!*first);
587 *first = child;
588 }
589 last = child;
590
591 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &child->stmt));
592 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &child->arg));
593 child->format = stmt->format;
594 LY_CHECK_RET(ly_dup_prefix_data(PARSER_CTX(ctx), stmt->format, stmt->prefix_data, &child->prefix_data));
595 child->flags = stmt->flags;
596 child->kw = stmt->kw;
597
598 /* recursively */
599 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &child->child));
600 }
601
602 return LY_SUCCESS;
603}
604
605/**
Radek Krejci335332a2019-09-05 13:03:35 +0200606 * @brief Parse extension instance.
607 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100608 * @param[in] ctx parser context.
609 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100610 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200611 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
612 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200613 * @return LY_ERR values.
614 */
615static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200616lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200617 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200618{
619 struct lysp_ext_instance *e;
620
Michal Vaskob36053d2020-03-26 15:49:30 +0100621 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200622
623 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200624 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100625 e->parent_stmt = insubstmt;
626 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200627 e->parsed = NULL;
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100628 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &e->child));
Radek Krejci335332a2019-09-05 13:03:35 +0200629
630 /* get optional argument */
631 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200632 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200633 }
634
635 return LY_SUCCESS;
636}
637
638/**
639 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
640 * description, etc...
641 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100642 * @param[in] ctx parser context.
643 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200644 * @param[in] substmt_index Index of this substatement.
645 * @param[in,out] value Place to store the parsed value.
646 * @param[in] arg Type of the YANG keyword argument (of the value).
647 * @param[in,out] exts Extension instances to add to.
648 *
649 * @return LY_ERR values.
650 */
651static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200652lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
653 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200654{
Radek Krejci335332a2019-09-05 13:03:35 +0200655 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200656 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200657 return LY_EVALID;
658 }
659
660 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200661 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200662
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100663 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
664 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200665 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100666 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200667 break;
668 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200669 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200670 return LY_EVALID;
671 }
672 }
673 return LY_SUCCESS;
674}
675
676/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200677 * @brief Parse a qname that can have more instances such as if-feature.
678 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100679 * @param[in] ctx parser context.
680 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200681 * @param[in,out] qnames Parsed qnames to add to.
682 * @param[in] arg Type of the expected argument.
683 * @param[in,out] exts Extension instances to add to.
684 *
685 * @return LY_ERR values.
686 */
687static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200688lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
689 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200690{
691 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200692
693 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
694
695 /* allocate new pointer */
696 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
697 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100698 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200699
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100700 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
701 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200702 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100703 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200704 break;
705 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200706 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200707 return LY_EVALID;
708 }
709 }
710 return LY_SUCCESS;
711}
712
713/**
Radek Krejci335332a2019-09-05 13:03:35 +0200714 * @brief Parse a generic text field that can have more instances such as base.
715 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100716 * @param[in] ctx parser context.
717 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200718 * @param[in,out] texts Parsed values to add to.
719 * @param[in] arg Type of the expected argument.
720 * @param[in,out] exts Extension instances to add to.
721 *
722 * @return LY_ERR values.
723 */
724static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200725lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
726 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200727{
728 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200729
730 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
731
732 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100733 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200734 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200735
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100736 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
737 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200738 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100739 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200740 break;
741 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200742 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200743 return LY_EVALID;
744 }
745 }
746 return LY_SUCCESS;
747}
748
749/**
750 * @brief Parse the status statement.
751 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100752 * @param[in] ctx parser context.
753 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200754 * @param[in,out] flags Flags to add to.
755 * @param[in,out] exts Extension instances to add to.
756 *
757 * @return LY_ERR values.
758 */
759static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200760lysp_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 +0200761{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200762 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200763
764 if (*flags & LYS_STATUS_MASK) {
765 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
766 return LY_EVALID;
767 }
768
769 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
770 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100771 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200772 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100773 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200774 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100775 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200776 *flags |= LYS_STATUS_OBSLT;
777 } else {
778 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
779 return LY_EVALID;
780 }
781
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100782 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
783 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200784 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100785 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200786 break;
787 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200788 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200789 return LY_EVALID;
790 }
791 }
792 return LY_SUCCESS;
793}
794
795/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100796 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200797 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100798 * @param[in] ctx parser context.
799 * @param[in] stmt Source statement data from the parsed extension instance.
800 * @param[in,out] when_p When pointer to parse to.
801 *
802 * @return LY_ERR values.
803 */
804static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200805lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100806{
807 LY_ERR ret = LY_SUCCESS;
808 struct lysp_when *when;
809
810 if (*when_p) {
811 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
812 return LY_EVALID;
813 }
814
815 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
816
817 when = calloc(1, sizeof *when);
818 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
819 *when_p = when;
820
821 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
822
823 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
824 switch (child->kw) {
825 case LY_STMT_DESCRIPTION:
826 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
827 break;
828 case LY_STMT_REFERENCE:
829 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
830 break;
831 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100832 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100833 break;
834 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200835 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100836 return LY_EVALID;
837 }
838 }
839 return ret;
840}
841
842/**
843 * @brief Parse the config statement.
844 *
845 * @param[in] ctx parser context.
846 * @param[in] stmt Source statement data from the parsed extension instance.
847 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200848 * @param[in,out] exts Extension instances to add to.
849 *
850 * @return LY_ERR values.
851 */
852static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200853lysp_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 +0200854{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200855 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200856
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100857 if (*flags & LYS_CONFIG_MASK) {
858 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
859 return LY_EVALID;
860 }
861
862 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
863 arg_len = strlen(stmt->arg);
864 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
865 *flags |= LYS_CONFIG_W;
866 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
867 *flags |= LYS_CONFIG_R;
868 } else {
869 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
870 return LY_EVALID;
871 }
872
873 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
874 switch (child->kw) {
875 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100876 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100877 break;
878 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200879 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100880 return LY_EVALID;
881 }
882 }
883
884 return LY_SUCCESS;
885}
886
887/**
888 * @brief Parse the mandatory statement.
889 *
890 * @param[in] ctx parser context.
891 * @param[in] stmt Source statement data from the parsed extension instance.
892 * @param[in,out] flags Flags to add to.
893 * @param[in,out] exts Extension instances to add to.
894 *
895 * @return LY_ERR values.
896 */
897static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200898lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200899 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100900{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200901 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100902
903 if (*flags & LYS_MAND_MASK) {
904 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
905 return LY_EVALID;
906 }
907
908 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
909 arg_len = strlen(stmt->arg);
910 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
911 *flags |= LYS_MAND_TRUE;
912 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
913 *flags |= LYS_MAND_FALSE;
914 } else {
915 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
916 return LY_EVALID;
917 }
918
919 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
920 switch (child->kw) {
921 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100922 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100923 break;
924 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200925 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100926 return LY_EVALID;
927 }
928 }
929
930 return LY_SUCCESS;
931}
932
933/**
934 * @brief Parse a restriction such as range or length.
935 *
936 * @param[in] ctx parser context.
937 * @param[in] stmt Source statement data from the parsed extension instance.
938 * @param[in,out] exts Extension instances to add to.
939 *
940 * @return LY_ERR values.
941 */
942static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200943lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100944{
Radek Krejci335332a2019-09-05 13:03:35 +0200945 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200946 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100947 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200948
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100949 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
950 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200951 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100952 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200953 break;
954 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100955 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200956 break;
957 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100958 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200959 break;
960 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100961 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200962 break;
963 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100964 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200965 break;
966 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200967 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200968 return LY_EVALID;
969 }
970 }
971 return LY_SUCCESS;
972}
973
974/**
975 * @brief Parse a restriction that can have more instances such as must.
976 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100977 * @param[in] ctx parser context.
978 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200979 * @param[in,out] restrs Restrictions to add to.
980 *
981 * @return LY_ERR values.
982 */
983static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200984lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200985{
986 struct lysp_restr *restr;
987
Michal Vaskob36053d2020-03-26 15:49:30 +0100988 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100989 return lysp_stmt_restr(ctx, stmt, restr);
990}
991
992/**
993 * @brief Parse the anydata or anyxml statement.
994 *
995 * @param[in] ctx parser context.
996 * @param[in] stmt Source statement data from the parsed extension instance.
997 * @param[in,out] siblings Siblings to add to.
998 *
999 * @return LY_ERR values.
1000 */
1001static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001002lysp_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 +01001003{
1004 struct lysp_node_anydata *any;
1005
1006 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1007
1008 /* create new structure and insert into siblings */
1009 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
1010
1011 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
1012 any->parent = parent;
1013
1014 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
1015
1016 /* parse substatements */
1017 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1018 switch (child->kw) {
1019 case LY_STMT_CONFIG:
1020 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
1021 break;
1022 case LY_STMT_DESCRIPTION:
1023 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
1024 break;
1025 case LY_STMT_IF_FEATURE:
1026 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
1027 break;
1028 case LY_STMT_MANDATORY:
1029 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
1030 break;
1031 case LY_STMT_MUST:
1032 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
1033 break;
1034 case LY_STMT_REFERENCE:
1035 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
1036 break;
1037 case LY_STMT_STATUS:
1038 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
1039 break;
1040 case LY_STMT_WHEN:
1041 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
1042 break;
1043 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001044 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001045 break;
1046 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001047 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1048 (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 +01001049 return LY_EVALID;
1050 }
1051 }
1052
1053 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +02001054}
1055
1056/**
1057 * @brief Parse the value or position statement. Substatement of type enum statement.
1058 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001059 * @param[in] ctx parser context.
1060 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001061 * @param[in,out] value Value to write to.
1062 * @param[in,out] flags Flags to write to.
1063 * @param[in,out] exts Extension instances to add to.
1064 *
1065 * @return LY_ERR values.
1066 */
1067static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001068lysp_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 +02001069 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001070{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001071 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001072 char *ptr = NULL;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001073 long long num = 0;
1074 unsigned long long unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +02001075
1076 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001077 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001078 return LY_EVALID;
1079 }
1080 *flags |= LYS_SET_VALUE;
1081
1082 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1083
1084 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001085 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
1086 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
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 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001092 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001093 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001094 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001095 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001096 goto error;
1097 }
1098 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001099 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001100 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001101 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001102 goto error;
1103 }
1104 }
1105 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001106 if (ptr - stmt->arg != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001107 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001108 goto error;
1109 }
1110 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001111 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001112 goto error;
1113 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001114 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +02001115 *value = num;
1116 } else {
1117 *value = unum;
1118 }
1119
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001120 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1121 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001122 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001123 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 +02001124 break;
1125 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001126 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001127 return LY_EVALID;
1128 }
1129 }
1130 return LY_SUCCESS;
1131
1132error:
1133 return LY_EVALID;
1134}
1135
1136/**
1137 * @brief Parse the enum or bit statement. Substatement of type statement.
1138 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001139 * @param[in] ctx parser context.
1140 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001141 * @param[in,out] enums Enums or bits to add to.
1142 *
1143 * @return LY_ERR values.
1144 */
1145static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001146lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +02001147{
1148 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +02001149
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001150 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 +02001151
Michal Vaskob36053d2020-03-26 15:49:30 +01001152 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001153
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001154 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +02001155 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
1156 } /* else nothing specific for YANG_BIT */
1157
Radek Krejci011e4aa2020-09-04 15:22:31 +02001158 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +02001159 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +02001160
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001161 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1162 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001163 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001164 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001165 break;
1166 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001167 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001168 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001169 break;
1170 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001171 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001172 break;
1173 case LY_STMT_STATUS:
1174 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
1175 break;
1176 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001177 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1178 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001179 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001180 break;
1181 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +02001182 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1183 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001184 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001185 break;
1186 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001187 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001188 break;
1189 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001190 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001191 return LY_EVALID;
1192 }
1193 }
Michal Vasko193dacd2022-10-13 08:43:05 +02001194
Radek Krejci335332a2019-09-05 13:03:35 +02001195 return LY_SUCCESS;
1196}
1197
1198/**
1199 * @brief Parse the fraction-digits statement. Substatement of type statement.
1200 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001201 * @param[in] ctx parser context.
1202 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001203 * @param[in,out] fracdig Value to write to.
1204 * @param[in,out] exts Extension instances to add to.
1205 *
1206 * @return LY_ERR values.
1207 */
1208static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001209lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001210 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001211{
1212 char *ptr;
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001213 int arg_len;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001214 unsigned long long num;
Radek Krejci335332a2019-09-05 13:03:35 +02001215
1216 if (*fracdig) {
1217 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1218 return LY_EVALID;
1219 }
1220
1221 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1222 arg_len = strlen(stmt->arg);
1223 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1224 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1225 return LY_EVALID;
1226 }
1227
1228 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001229 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001230 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001231 if (ptr - stmt->arg != arg_len) {
Radek Krejci335332a2019-09-05 13:03:35 +02001232 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1233 return LY_EVALID;
1234 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001235 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001236 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1237 return LY_EVALID;
1238 }
1239 *fracdig = num;
1240
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001241 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1242 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001243 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001244 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001245 break;
1246 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001247 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001248 return LY_EVALID;
1249 }
1250 }
1251 return LY_SUCCESS;
1252}
1253
1254/**
1255 * @brief Parse the require-instance statement. Substatement of type statement.
1256 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001257 * @param[in] ctx parser context.
1258 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001259 * @param[in,out] reqinst Value to write to.
1260 * @param[in,out] flags Flags to write to.
1261 * @param[in,out] exts Extension instances to add to.
1262 *
1263 * @return LY_ERR values.
1264 */
1265static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001266lysp_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 +02001267 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001268{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001269 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001270
1271 if (*flags & LYS_SET_REQINST) {
1272 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1273 return LY_EVALID;
1274 }
1275 *flags |= LYS_SET_REQINST;
1276
1277 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1278 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001279 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001280 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001281 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001282 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1283 return LY_EVALID;
1284 }
1285
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001286 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1287 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001288 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001289 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001290 break;
1291 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001292 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001293 return LY_EVALID;
1294 }
1295 }
1296 return LY_SUCCESS;
1297}
1298
1299/**
1300 * @brief Parse the modifier statement. Substatement of type pattern statement.
1301 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001302 * @param[in] ctx parser context.
1303 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001304 * @param[in,out] pat Value to write to.
1305 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001306 * @return LY_ERR values.
1307 */
1308static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001309lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001310 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001311{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001312 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001313 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001314
Radek Krejcif13b87b2020-12-01 22:02:17 +01001315 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001316 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1317 return LY_EVALID;
1318 }
1319
1320 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1321 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001322 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001323 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1324 return LY_EVALID;
1325 }
1326
1327 /* replace the value in the dictionary */
1328 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001329 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001330 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001331 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001332
Radek Krejcif13b87b2020-12-01 22:02:17 +01001333 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1334 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001335 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001336
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001337 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1338 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001339 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001340 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001341 break;
1342 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001343 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001344 return LY_EVALID;
1345 }
1346 }
1347 return LY_SUCCESS;
1348}
1349
1350/**
1351 * @brief Parse the pattern statement. Substatement of type statement.
1352 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001353 * @param[in] ctx parser context.
1354 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001355 * @param[in,out] patterns Restrictions to add to.
1356 *
1357 * @return LY_ERR values.
1358 */
1359static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001360lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001361{
1362 char *buf;
1363 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001364 struct lysp_restr *restr;
1365
1366 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001367 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001368 arg_len = strlen(stmt->arg);
1369
1370 /* add special meaning first byte */
1371 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001372 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001373 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001374 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001375 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001376 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001377 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001378
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001379 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1380 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001381 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001382 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001383 break;
1384 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001385 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001386 break;
1387 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001388 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001389 break;
1390 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001391 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001392 break;
1393 case LY_STMT_MODIFIER:
1394 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001395 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001396 break;
1397 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001398 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001399 break;
1400 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001401 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001402 return LY_EVALID;
1403 }
1404 }
1405 return LY_SUCCESS;
1406}
1407
1408/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001409 * @brief Parse the deviate statement. Substatement of deviation statement.
1410 *
1411 * @param[in] ctx parser context.
1412 * @param[in] stmt Source statement data from the parsed extension instance.
1413 * @param[in,out] devs Array of deviates to add to.
1414 * @param[in,out] exts Extension instances to add to.
1415 * @return LY_ERR values.
1416 */
1417static LY_ERR
1418lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1419{
1420 (void)stmt;
1421 (void)devs;
1422 (void)exts;
1423
1424 /* TODO */
1425 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1426 return LY_EINVAL;
1427}
1428
1429/**
1430 * @brief Parse the deviation statement.
1431 *
1432 * @param[in] ctx parser context.
1433 * @param[in] stmt Source statement data from the parsed extension instance.
1434 * @param[in,out] deviations Array of deviations to add to.
1435 * @return LY_ERR values.
1436 */
1437static LY_ERR
1438lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1439{
1440 struct lysp_deviation *dev;
1441
1442 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1443
1444 /* store nodeid */
1445 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1446 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1447
1448 /* parse substatements */
1449 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1450 switch (child->kw) {
1451 case LY_STMT_DESCRIPTION:
1452 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1453 break;
1454 case LY_STMT_DEVIATE:
1455 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1456 break;
1457 case LY_STMT_REFERENCE:
1458 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1459 break;
1460 case LY_STMT_EXTENSION_INSTANCE:
1461 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1462 break;
1463 default:
1464 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1465 return LY_EVALID;
1466 }
1467 }
1468
1469 return LY_SUCCESS;
1470}
1471
1472/**
1473 * @brief Parse the yang-version statement.
1474 *
1475 * @param[in] ctx parser context.
1476 * @param[in] stmt Source statement data from the parsed extension instance.
1477 * @param[out] version Version to write to.
1478 * @param[in,out] exts Extension instances to add to.
1479 * @return LY_ERR values.
1480 */
1481static LY_ERR
1482lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1483{
1484 if (*version) {
1485 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1486 return LY_EVALID;
1487 }
1488
1489 /* store flag */
1490 if (!strcmp(stmt->arg, "1")) {
1491 *version = LYS_VERSION_1_0;
1492 } else if (!strcmp(stmt->arg, "1.1")) {
1493 *version = LYS_VERSION_1_1;
1494 } else {
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001495 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, (int)strlen(stmt->arg), stmt->arg, "yang-version");
Michal Vasko193dacd2022-10-13 08:43:05 +02001496 return LY_EVALID;
1497 }
1498
1499 /* parse substatements */
1500 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1501 switch (child->kw) {
1502 case LY_STMT_EXTENSION_INSTANCE:
1503 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1504 break;
1505 default:
1506 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1507 return LY_EVALID;
1508 }
1509 }
1510
1511 return LY_SUCCESS;
1512}
1513
1514/**
1515 * @brief Parse the module statement.
1516 *
1517 * @param[in] ctx parser context.
1518 * @param[in] stmt Source statement data from the parsed extension instance.
1519 * @param[in,out] mod Module to fill.
1520 * @return LY_ERR values.
1521 */
1522static LY_ERR
1523lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1524{
1525 (void)stmt;
1526 (void)mod;
1527
1528 /* TODO */
1529 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1530 return LY_EINVAL;
1531}
1532
1533/**
1534 * @brief Parse the submodule statement.
1535 *
1536 * @param[in] ctx parser context.
1537 * @param[in] stmt Source statement data from the parsed extension instance.
1538 * @param[in,out] submod Module to fill.
1539 * @return LY_ERR values.
1540 */
1541static LY_ERR
1542lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1543{
1544 (void)stmt;
1545 (void)submod;
1546
1547 /* TODO */
1548 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1549 return LY_EINVAL;
1550}
1551
1552/**
1553 * @brief Parse the yin-element statement. Substatement of argument statement.
1554 *
1555 * @param[in] ctx parser context.
1556 * @param[in] stmt Source statement data from the parsed extension instance.
1557 * @param[in,out] flags Flags to write to.
1558 * @param[in,out] exts Extension instances to add to.
1559 * @return LY_ERR values.
1560 */
1561static LY_ERR
1562lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1563{
1564 if (*flags & LYS_YINELEM_MASK) {
1565 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1566 return LY_EVALID;
1567 }
1568
1569 /* store flag */
1570 if (!strcmp(stmt->arg, "true")) {
1571 *flags |= LYS_YINELEM_TRUE;
1572 } else if (!strcmp(stmt->arg, "false")) {
1573 *flags |= LYS_YINELEM_FALSE;
1574 } else {
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001575 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, (int)strlen(stmt->arg), stmt->arg, "yin-element");
Michal Vasko193dacd2022-10-13 08:43:05 +02001576 return LY_EVALID;
1577 }
1578
1579 /* parse substatements */
1580 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1581 switch (child->kw) {
1582 case LY_STMT_EXTENSION_INSTANCE:
1583 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1584 break;
1585 default:
1586 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1587 return LY_EVALID;
1588 }
1589 }
1590
1591 return LY_SUCCESS;
1592}
1593
1594/**
1595 * @brief Parse the argument statement. Substatement of extension statement.
1596 *
1597 * @param[in] ctx parser context.
1598 * @param[in] stmt Source statement data from the parsed extension instance.
1599 * @param[in,out] ex Extension to fill.
1600 * @return LY_ERR values.
1601 */
1602static LY_ERR
1603lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1604{
1605 if (ex->argname) {
1606 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1607 return LY_EVALID;
1608 }
1609
1610 /* store argument name */
1611 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1612 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1613
1614 /* parse substatements */
1615 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1616 switch (child->kw) {
1617 case LY_STMT_YIN_ELEMENT:
1618 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1619 break;
1620 case LY_STMT_EXTENSION_INSTANCE:
1621 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1622 break;
1623 default:
1624 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1625 return LY_EVALID;
1626 }
1627 }
1628
1629 return LY_SUCCESS;
1630}
1631
1632/**
1633 * @brief Parse the extension statement.
1634 *
1635 * @param[in] ctx parser context.
1636 * @param[in] stmt Source statement data from the parsed extension instance.
1637 * @param[in,out] extensions Array of extensions to add to.
1638 * @return LY_ERR values.
1639 */
1640static LY_ERR
1641lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1642{
1643 struct lysp_ext *ex;
1644
1645 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1646
1647 /* store name */
1648 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1649 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1650
1651 /* parse substatements */
1652 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1653 switch (child->kw) {
1654 case LY_STMT_DESCRIPTION:
1655 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1656 break;
1657 case LY_STMT_REFERENCE:
1658 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1659 break;
1660 case LY_STMT_STATUS:
1661 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1662 break;
1663 case LY_STMT_ARGUMENT:
1664 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1665 break;
1666 case LY_STMT_EXTENSION_INSTANCE:
1667 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1668 break;
1669 default:
1670 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1671 return LY_EVALID;
1672 }
1673 }
1674
1675 return LY_SUCCESS;
1676}
1677
1678/**
1679 * @brief Parse the feature statement.
1680 *
1681 * @param[in] ctx parser context.
1682 * @param[in] stmt Source statement data from the parsed extension instance.
1683 * @param[in,out] features Array of features to add to.
1684 * @return LY_ERR values.
1685 */
1686static LY_ERR
1687lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1688{
1689 struct lysp_feature *feat;
1690
1691 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1692
1693 /* store name */
1694 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1695 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1696
1697 /* parse substatements */
1698 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1699 switch (child->kw) {
1700 case LY_STMT_DESCRIPTION:
1701 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1702 break;
1703 case LY_STMT_IF_FEATURE:
1704 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1705 break;
1706 case LY_STMT_REFERENCE:
1707 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1708 break;
1709 case LY_STMT_STATUS:
1710 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1711 break;
1712 case LY_STMT_EXTENSION_INSTANCE:
1713 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1714 break;
1715 default:
1716 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1717 return LY_EVALID;
1718 }
1719 }
1720
1721 return LY_SUCCESS;
1722}
1723
1724/**
1725 * @brief Parse the identity statement.
1726 *
1727 * @param[in] ctx parser context.
1728 * @param[in] stmt Source statement data from the parsed extension instance.
1729 * @param[in,out] identities Array of identities to add to.
1730 * @return LY_ERR values.
1731 */
1732static LY_ERR
1733lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1734{
1735 struct lysp_ident *ident;
1736
1737 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1738
1739 /* store name */
1740 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1741 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1742
1743 /* parse substatements */
1744 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1745 switch (child->kw) {
1746 case LY_STMT_DESCRIPTION:
1747 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1748 break;
1749 case LY_STMT_IF_FEATURE:
1750 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1751 break;
1752 case LY_STMT_REFERENCE:
1753 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1754 break;
1755 case LY_STMT_STATUS:
1756 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1757 break;
1758 case LY_STMT_BASE:
1759 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1760 break;
1761 case LY_STMT_EXTENSION_INSTANCE:
1762 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1763 break;
1764 default:
1765 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1766 return LY_EVALID;
1767 }
1768 }
1769
1770 return LY_SUCCESS;
1771}
1772
1773/**
1774 * @brief Parse the import statement.
1775 *
1776 * @param[in] ctx parser context.
1777 * @param[in] stmt Source statement data from the parsed extension instance.
1778 * @param[in,out] imports Array of imports to add to.
1779 * @return LY_ERR values.
1780 */
1781static LY_ERR
1782lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1783{
1784 struct lysp_import *imp;
1785 const char *str = NULL;
1786
1787 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1788
1789 /* store name */
1790 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1791 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1792
1793 /* parse substatements */
1794 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1795 switch (child->kw) {
1796 case LY_STMT_PREFIX:
1797 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1798 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1799 break;
1800 case LY_STMT_DESCRIPTION:
1801 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1802 break;
1803 case LY_STMT_REFERENCE:
1804 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1805 break;
1806 case LY_STMT_REVISION_DATE:
1807 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1808 strcpy(imp->rev, str);
1809 lydict_remove(PARSER_CTX(ctx), str);
1810 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1811 break;
1812 case LY_STMT_EXTENSION_INSTANCE:
1813 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1814 break;
1815 default:
1816 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1817 return LY_EVALID;
1818 }
1819 }
1820
1821 return LY_SUCCESS;
1822}
1823
1824/**
1825 * @brief Parse the include statement.
1826 *
1827 * @param[in] ctx parser context.
1828 * @param[in] stmt Source statement data from the parsed extension instance.
1829 * @param[in,out] includes Array of identities to add to.
1830 * @return LY_ERR values.
1831 */
1832static LY_ERR
1833lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1834{
1835 struct lysp_include *inc;
1836 const char *str = NULL;
1837
1838 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1839
1840 /* store name */
1841 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1842 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1843
1844 /* parse substatements */
1845 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1846 switch (child->kw) {
1847 case LY_STMT_DESCRIPTION:
1848 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1849 break;
1850 case LY_STMT_REFERENCE:
1851 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1852 break;
1853 case LY_STMT_REVISION_DATE:
1854 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1855 strcpy(inc->rev, str);
1856 lydict_remove(PARSER_CTX(ctx), str);
1857 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1858 break;
1859 case LY_STMT_EXTENSION_INSTANCE:
1860 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1861 break;
1862 default:
1863 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1864 return LY_EVALID;
1865 }
1866 }
1867
1868 return LY_SUCCESS;
1869}
1870
1871/**
1872 * @brief Parse the revision statement.
1873 *
1874 * @param[in] ctx parser context.
1875 * @param[in] stmt Source statement data from the parsed extension instance.
1876 * @param[in,out] includes Array of identities to add to.
1877 * @return LY_ERR values.
1878 */
1879static LY_ERR
1880lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1881{
1882 struct lysp_revision *rev;
1883
1884 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1885
1886 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001887 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001888 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001889
1890 /* parse substatements */
1891 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1892 switch (child->kw) {
1893 case LY_STMT_DESCRIPTION:
1894 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1895 break;
1896 case LY_STMT_REFERENCE:
1897 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1898 break;
1899 case LY_STMT_EXTENSION_INSTANCE:
1900 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1901 break;
1902 default:
1903 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1904 return LY_EVALID;
1905 }
1906 }
1907
1908 return LY_SUCCESS;
1909}
1910
1911/**
Radek Krejci335332a2019-09-05 13:03:35 +02001912 * @brief Parse the type statement.
1913 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001914 * @param[in] ctx parser context.
1915 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001916 * @param[in,out] type Type to wrote to.
1917 *
1918 * @return LY_ERR values.
1919 */
1920static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001921lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001922{
1923 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001924 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001925 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001926
1927 if (type->name) {
1928 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1929 return LY_EVALID;
1930 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001931
1932 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001933 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001934 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001935
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001936 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1937 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001938 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001939 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001940 type->flags |= LYS_SET_BASE;
1941 break;
1942 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001943 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001944 type->flags |= LYS_SET_BIT;
1945 break;
1946 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001947 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001948 type->flags |= LYS_SET_ENUM;
1949 break;
1950 case LY_STMT_FRACTION_DIGITS:
1951 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1952 type->flags |= LYS_SET_FRDIGITS;
1953 break;
1954 case LY_STMT_LENGTH:
1955 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001956 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001957 return LY_EVALID;
1958 }
1959 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001960 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001961
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001962 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001963 type->flags |= LYS_SET_LENGTH;
1964 break;
1965 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001966 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001967 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001968 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001969 lydict_remove(PARSER_CTX(ctx), str_path);
1970 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001971 type->flags |= LYS_SET_PATH;
1972 break;
1973 case LY_STMT_PATTERN:
1974 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1975 type->flags |= LYS_SET_PATTERN;
1976 break;
1977 case LY_STMT_RANGE:
1978 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001979 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001980 return LY_EVALID;
1981 }
1982 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001983 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001984
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001985 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001986 type->flags |= LYS_SET_RANGE;
1987 break;
1988 case LY_STMT_REQUIRE_INSTANCE:
1989 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001990 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001991 break;
1992 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001993 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001994 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1995 type->flags |= LYS_SET_TYPE;
1996 break;
1997 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001998 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001999 break;
2000 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002001 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02002002 return LY_EVALID;
2003 }
2004 }
2005 return LY_SUCCESS;
2006}
2007
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002008/**
2009 * @brief Parse the leaf statement.
2010 *
2011 * @param[in] ctx parser context.
2012 * @param[in] stmt Source statement data from the parsed extension instance.
2013 * @param[in] parent Parent node to connect to (not into).
2014 * @param[in,out] siblings Siblings to add to.
2015 *
2016 * @return LY_ERR values.
2017 */
2018static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002019lysp_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 +01002020{
2021 struct lysp_node_leaf *leaf;
2022
2023 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2024
2025 /* create new leaf structure */
2026 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
2027 leaf->nodetype = LYS_LEAF;
2028 leaf->parent = parent;
2029
2030 /* get name */
2031 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
2032
2033 /* parse substatements */
2034 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2035 switch (child->kw) {
2036 case LY_STMT_CONFIG:
2037 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
2038 break;
2039 case LY_STMT_DEFAULT:
2040 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 +01002041 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002042 break;
2043 case LY_STMT_DESCRIPTION:
2044 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
2045 break;
2046 case LY_STMT_IF_FEATURE:
2047 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
2048 break;
2049 case LY_STMT_MANDATORY:
2050 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
2051 break;
2052 case LY_STMT_MUST:
2053 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
2054 break;
2055 case LY_STMT_REFERENCE:
2056 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
2057 break;
2058 case LY_STMT_STATUS:
2059 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
2060 break;
2061 case LY_STMT_TYPE:
2062 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
2063 break;
2064 case LY_STMT_UNITS:
2065 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
2066 break;
2067 case LY_STMT_WHEN:
2068 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
2069 break;
2070 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002071 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002072 break;
2073 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002074 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002075 return LY_EVALID;
2076 }
2077 }
2078
2079 /* mandatory substatements */
2080 if (!leaf->type.name) {
2081 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
2082 return LY_EVALID;
2083 }
2084
2085 return LY_SUCCESS;
2086}
2087
2088/**
2089 * @brief Parse the max-elements statement.
2090 *
2091 * @param[in] ctx parser context.
2092 * @param[in] stmt Source statement data from the parsed extension instance.
2093 * @param[in,out] max Value to write to.
2094 * @param[in,out] flags Flags to write to.
2095 * @param[in,out] exts Extension instances to add to.
2096 *
2097 * @return LY_ERR values.
2098 */
2099static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002100lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
2101 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002102{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002103 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002104 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002105 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002106
2107 if (*flags & LYS_SET_MAX) {
2108 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
2109 return LY_EVALID;
2110 }
2111 *flags |= LYS_SET_MAX;
2112
2113 /* get value */
2114 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2115 arg_len = strlen(stmt->arg);
2116
2117 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
2118 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
2119 return LY_EVALID;
2120 }
2121
2122 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
2123 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002124 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002125 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002126 if (ptr - stmt->arg != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002127 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
2128 return LY_EVALID;
2129 }
2130 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2131 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
2132 return LY_EVALID;
2133 }
2134
2135 *max = num;
2136 } else {
2137 /* unbounded */
2138 *max = 0;
2139 }
2140
2141 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2142 switch (child->kw) {
2143 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002144 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002145 break;
2146 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002147 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002148 return LY_EVALID;
2149 }
2150 }
2151
2152 return LY_SUCCESS;
2153}
2154
2155/**
2156 * @brief Parse the min-elements statement.
2157 *
2158 * @param[in] ctx parser context.
2159 * @param[in] stmt Source statement data from the parsed extension instance.
2160 * @param[in,out] min Value to write to.
2161 * @param[in,out] flags Flags to write to.
2162 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002163 * @return LY_ERR values.
2164 */
2165static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002166lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
2167 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002168{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002169 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002170 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002171 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002172
2173 if (*flags & LYS_SET_MIN) {
2174 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
2175 return LY_EVALID;
2176 }
2177 *flags |= LYS_SET_MIN;
2178
2179 /* get value */
2180 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2181 arg_len = strlen(stmt->arg);
2182
2183 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
2184 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2185 return LY_EVALID;
2186 }
2187
2188 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002189 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002190 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002191 if (ptr - stmt->arg != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002192 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2193 return LY_EVALID;
2194 }
2195 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2196 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
2197 return LY_EVALID;
2198 }
2199 *min = num;
2200
2201 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2202 switch (child->kw) {
2203 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002204 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002205 break;
2206 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002207 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002208 return LY_EVALID;
2209 }
2210 }
2211
2212 return LY_SUCCESS;
2213}
2214
2215/**
2216 * @brief Parse the ordered-by statement.
2217 *
2218 * @param[in] ctx parser context.
2219 * @param[in] stmt Source statement data from the parsed extension instance.
2220 * @param[in,out] flags Flags to write to.
2221 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002222 * @return LY_ERR values.
2223 */
2224static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002225lysp_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 +01002226{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002227 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002228
2229 if (*flags & LYS_ORDBY_MASK) {
2230 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2231 return LY_EVALID;
2232 }
2233
2234 /* get value */
2235 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2236 arg_len = strlen(stmt->arg);
2237 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2238 *flags |= LYS_MAND_TRUE;
2239 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2240 *flags |= LYS_MAND_FALSE;
2241 } else {
2242 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2243 return LY_EVALID;
2244 }
2245
2246 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2247 switch (child->kw) {
2248 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002249 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002250 break;
2251 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002252 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002253 return LY_EVALID;
2254 }
2255 }
2256
2257 return LY_SUCCESS;
2258}
2259
2260/**
2261 * @brief Parse the leaf-list statement.
2262 *
2263 * @param[in] ctx parser context.
2264 * @param[in] stmt Source statement data from the parsed extension instance.
2265 * @param[in] parent Parent node to connect to (not into).
2266 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002267 * @return LY_ERR values.
2268 */
2269static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002270lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002271 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002272{
2273 struct lysp_node_leaflist *llist;
2274
2275 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2276
2277 /* create new leaf-list structure */
2278 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2279 llist->nodetype = LYS_LEAFLIST;
2280 llist->parent = parent;
2281
2282 /* get name */
2283 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2284
2285 /* parse substatements */
2286 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2287 switch (child->kw) {
2288 case LY_STMT_CONFIG:
2289 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2290 break;
2291 case LY_STMT_DEFAULT:
2292 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2293 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2294 break;
2295 case LY_STMT_DESCRIPTION:
2296 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2297 break;
2298 case LY_STMT_IF_FEATURE:
2299 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2300 break;
2301 case LY_STMT_MAX_ELEMENTS:
2302 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2303 break;
2304 case LY_STMT_MIN_ELEMENTS:
2305 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2306 break;
2307 case LY_STMT_MUST:
2308 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2309 break;
2310 case LY_STMT_ORDERED_BY:
2311 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2312 break;
2313 case LY_STMT_REFERENCE:
2314 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2315 break;
2316 case LY_STMT_STATUS:
2317 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2318 break;
2319 case LY_STMT_TYPE:
2320 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2321 break;
2322 case LY_STMT_UNITS:
2323 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2324 break;
2325 case LY_STMT_WHEN:
2326 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2327 break;
2328 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002329 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002330 break;
2331 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002332 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002333 return LY_EVALID;
2334 }
2335 }
2336
2337 /* mandatory substatements */
2338 if (!llist->type.name) {
2339 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2340 return LY_EVALID;
2341 }
2342
2343 return LY_SUCCESS;
2344}
2345
2346/**
2347 * @brief Parse the refine statement.
2348 *
2349 * @param[in] ctx parser context.
2350 * @param[in] stmt Source statement data from the parsed extension instance.
2351 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002352 * @return LY_ERR values.
2353 */
2354static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002355lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002356{
2357 struct lysp_refine *rf;
2358
2359 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2360
2361 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2362
2363 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2364
2365 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2366 switch (child->kw) {
2367 case LY_STMT_CONFIG:
2368 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2369 break;
2370 case LY_STMT_DEFAULT:
2371 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2372 break;
2373 case LY_STMT_DESCRIPTION:
2374 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2375 break;
2376 case LY_STMT_IF_FEATURE:
2377 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2378 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2379 break;
2380 case LY_STMT_MAX_ELEMENTS:
2381 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2382 break;
2383 case LY_STMT_MIN_ELEMENTS:
2384 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2385 break;
2386 case LY_STMT_MUST:
2387 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2388 break;
2389 case LY_STMT_MANDATORY:
2390 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2391 break;
2392 case LY_STMT_REFERENCE:
2393 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2394 break;
2395 case LY_STMT_PRESENCE:
2396 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2397 break;
2398 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002399 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002400 break;
2401 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002402 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002403 return LY_EVALID;
2404 }
2405 }
2406
2407 return LY_SUCCESS;
2408}
2409
2410/**
2411 * @brief Parse the typedef statement.
2412 *
2413 * @param[in] ctx parser context.
2414 * @param[in] stmt Source statement data from the parsed extension instance.
2415 * @param[in] parent Parent node to connect to (not into).
2416 * @param[in,out] typedefs Typedefs to add to.
2417 *
2418 * @return LY_ERR values.
2419 */
2420static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002421lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002422 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002423{
2424 struct lysp_tpdf *tpdf;
2425
2426 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2427
2428 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2429
2430 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2431
2432 /* parse substatements */
2433 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2434 switch (child->kw) {
2435 case LY_STMT_DEFAULT:
2436 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 +01002437 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002438 break;
2439 case LY_STMT_DESCRIPTION:
2440 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2441 break;
2442 case LY_STMT_REFERENCE:
2443 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2444 break;
2445 case LY_STMT_STATUS:
2446 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2447 break;
2448 case LY_STMT_TYPE:
2449 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2450 break;
2451 case LY_STMT_UNITS:
2452 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2453 break;
2454 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002455 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002456 break;
2457 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002458 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002459 return LY_EVALID;
2460 }
2461 }
2462
2463 /* mandatory substatements */
2464 if (!tpdf->type.name) {
2465 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2466 return LY_EVALID;
2467 }
2468
2469 /* store data for collision check */
2470 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2471 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2472 }
2473
2474 return LY_SUCCESS;
2475}
2476
2477/**
2478 * @brief Parse the input or output statement.
2479 *
2480 * @param[in] ctx parser context.
2481 * @param[in] stmt Source statement data from the parsed extension instance.
2482 * @param[in] parent Parent node to connect to (not into).
2483 * @param[in,out] inout_p Input/output pointer to write to.
2484 *
2485 * @return LY_ERR values.
2486 */
2487static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002488lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002489 struct lysp_node_action_inout *inout_p)
2490{
2491 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002492 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002493 return LY_EVALID;
2494 }
2495
2496 /* initiate structure */
2497 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2498 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2499 inout_p->parent = parent;
2500
2501 /* parse substatements */
2502 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2503 switch (child->kw) {
2504 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002505 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002506 /* fall through */
2507 case LY_STMT_ANYXML:
2508 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2509 break;
2510 case LY_STMT_CHOICE:
2511 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2512 break;
2513 case LY_STMT_CONTAINER:
2514 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2515 break;
2516 case LY_STMT_LEAF:
2517 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2518 break;
2519 case LY_STMT_LEAF_LIST:
2520 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2521 break;
2522 case LY_STMT_LIST:
2523 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2524 break;
2525 case LY_STMT_USES:
2526 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2527 break;
2528 case LY_STMT_TYPEDEF:
2529 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2530 break;
2531 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002532 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002533 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2534 break;
2535 case LY_STMT_GROUPING:
2536 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2537 break;
2538 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002539 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002540 break;
2541 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002542 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002543 return LY_EVALID;
2544 }
2545 }
2546
2547 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002548 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002549 return LY_EVALID;
2550 }
2551
2552 return LY_SUCCESS;
2553}
2554
2555/**
2556 * @brief Parse the action statement.
2557 *
2558 * @param[in] ctx parser context.
2559 * @param[in] stmt Source statement data from the parsed extension instance.
2560 * @param[in] parent Parent node to connect to (not into).
2561 * @param[in,out] actions Actions to add to.
2562 *
2563 * @return LY_ERR values.
2564 */
2565static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002566lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002567 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002568{
2569 struct lysp_node_action *act;
2570
2571 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2572
2573 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2574
2575 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2576 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2577 act->parent = parent;
2578
2579 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2580 switch (child->kw) {
2581 case LY_STMT_DESCRIPTION:
2582 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2583 break;
2584 case LY_STMT_IF_FEATURE:
2585 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2586 break;
2587 case LY_STMT_REFERENCE:
2588 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2589 break;
2590 case LY_STMT_STATUS:
2591 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2592 break;
2593
2594 case LY_STMT_INPUT:
2595 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2596 break;
2597 case LY_STMT_OUTPUT:
2598 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2599 break;
2600
2601 case LY_STMT_TYPEDEF:
2602 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2603 break;
2604 case LY_STMT_GROUPING:
2605 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2606 break;
2607 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002608 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 +01002609 break;
2610 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002611 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002612 return LY_EVALID;
2613 }
2614 }
2615
2616 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2617 if (!act->input.nodetype) {
2618 act->input.nodetype = LYS_INPUT;
2619 act->input.parent = &act->node;
2620 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2621 }
2622 if (!act->output.nodetype) {
2623 act->output.nodetype = LYS_OUTPUT;
2624 act->output.parent = &act->node;
2625 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2626 }
2627
2628 return LY_SUCCESS;
2629}
2630
2631/**
2632 * @brief Parse the notification statement.
2633 *
2634 * @param[in] ctx parser context.
2635 * @param[in] stmt Source statement data from the parsed extension instance.
2636 * @param[in] parent Parent node to connect to (not into).
2637 * @param[in,out] notifs Notifications to add to.
2638 *
2639 * @return LY_ERR values.
2640 */
2641static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002642lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002643 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002644{
2645 struct lysp_node_notif *notif;
2646
2647 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2648
2649 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2650
2651 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2652 notif->nodetype = LYS_NOTIF;
2653 notif->parent = parent;
2654
2655 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2656 switch (child->kw) {
2657 case LY_STMT_DESCRIPTION:
2658 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2659 break;
2660 case LY_STMT_IF_FEATURE:
2661 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2662 break;
2663 case LY_STMT_REFERENCE:
2664 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2665 break;
2666 case LY_STMT_STATUS:
2667 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2668 break;
2669
2670 case LY_STMT_ANYDATA:
2671 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2672 /* fall through */
2673 case LY_STMT_ANYXML:
2674 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2675 break;
2676 case LY_STMT_CHOICE:
2677 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2678 break;
2679 case LY_STMT_CONTAINER:
2680 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2681 break;
2682 case LY_STMT_LEAF:
2683 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2684 break;
2685 case LY_STMT_LEAF_LIST:
2686 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2687 break;
2688 case LY_STMT_LIST:
2689 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2690 break;
2691 case LY_STMT_USES:
2692 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2693 break;
2694
2695 case LY_STMT_MUST:
2696 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2697 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2698 break;
2699 case LY_STMT_TYPEDEF:
2700 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2701 break;
2702 case LY_STMT_GROUPING:
2703 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2704 break;
2705 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002706 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002707 break;
2708 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002709 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002710 return LY_EVALID;
2711 }
2712 }
2713
2714 return LY_SUCCESS;
2715}
2716
2717/**
2718 * @brief Parse the grouping statement.
2719 *
2720 * @param[in] ctx parser context.
2721 * @param[in] stmt Source statement data from the parsed extension instance.
2722 * @param[in] parent Parent node to connect to (not into).
2723 * @param[in,out] groupings Groupings to add to.
2724 *
2725 * @return LY_ERR values.
2726 */
2727static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002728lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002729 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002730{
2731 struct lysp_node_grp *grp;
2732
2733 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2734
2735 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2736
2737 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2738 grp->nodetype = LYS_GROUPING;
2739 grp->parent = parent;
2740
2741 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2742 switch (child->kw) {
2743 case LY_STMT_DESCRIPTION:
2744 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2745 break;
2746 case LY_STMT_REFERENCE:
2747 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2748 break;
2749 case LY_STMT_STATUS:
2750 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2751 break;
2752
2753 case LY_STMT_ANYDATA:
2754 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2755 /* fall through */
2756 case LY_STMT_ANYXML:
2757 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2758 break;
2759 case LY_STMT_CHOICE:
2760 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2761 break;
2762 case LY_STMT_CONTAINER:
2763 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2764 break;
2765 case LY_STMT_LEAF:
2766 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2767 break;
2768 case LY_STMT_LEAF_LIST:
2769 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2770 break;
2771 case LY_STMT_LIST:
2772 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2773 break;
2774 case LY_STMT_USES:
2775 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2776 break;
2777
2778 case LY_STMT_TYPEDEF:
2779 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2780 break;
2781 case LY_STMT_ACTION:
2782 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2783 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2784 break;
2785 case LY_STMT_GROUPING:
2786 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2787 break;
2788 case LY_STMT_NOTIFICATION:
2789 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2790 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2791 break;
2792 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002793 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002794 break;
2795 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002796 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002797 return LY_EVALID;
2798 }
2799 }
2800
2801 return LY_SUCCESS;
2802}
2803
2804/**
2805 * @brief Parse the augment statement.
2806 *
2807 * @param[in] ctx parser context.
2808 * @param[in] stmt Source statement data from the parsed extension instance.
2809 * @param[in] parent Parent node to connect to (not into).
2810 * @param[in,out] augments Augments to add to.
2811 *
2812 * @return LY_ERR values.
2813 */
2814static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002815lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002816 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002817{
2818 struct lysp_node_augment *aug;
2819
2820 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2821
2822 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2823
2824 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2825 aug->nodetype = LYS_AUGMENT;
2826 aug->parent = parent;
2827
2828 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2829 switch (child->kw) {
2830 case LY_STMT_DESCRIPTION:
2831 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2832 break;
2833 case LY_STMT_IF_FEATURE:
2834 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2835 break;
2836 case LY_STMT_REFERENCE:
2837 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2838 break;
2839 case LY_STMT_STATUS:
2840 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2841 break;
2842 case LY_STMT_WHEN:
2843 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2844 break;
2845
2846 case LY_STMT_ANYDATA:
2847 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2848 /* fall through */
2849 case LY_STMT_ANYXML:
2850 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2851 break;
2852 case LY_STMT_CASE:
2853 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2854 break;
2855 case LY_STMT_CHOICE:
2856 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2857 break;
2858 case LY_STMT_CONTAINER:
2859 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2860 break;
2861 case LY_STMT_LEAF:
2862 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2863 break;
2864 case LY_STMT_LEAF_LIST:
2865 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2866 break;
2867 case LY_STMT_LIST:
2868 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2869 break;
2870 case LY_STMT_USES:
2871 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2872 break;
2873
2874 case LY_STMT_ACTION:
2875 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2876 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2877 break;
2878 case LY_STMT_NOTIFICATION:
2879 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2880 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2881 break;
2882 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002883 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002884 break;
2885 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002886 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002887 return LY_EVALID;
2888 }
2889 }
2890
2891 return LY_SUCCESS;
2892}
2893
2894/**
2895 * @brief Parse the uses statement.
2896 *
2897 * @param[in] ctx parser context.
2898 * @param[in] stmt Source statement data from the parsed extension instance.
2899 * @param[in] parent Parent node to connect to (not into).
2900 * @param[in,out] siblings Siblings to add to.
2901 *
2902 * @return LY_ERR values.
2903 */
2904static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002905lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002906 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002907{
2908 struct lysp_node_uses *uses;
2909
2910 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2911
2912 /* create uses structure */
2913 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2914
2915 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2916 uses->nodetype = LYS_USES;
2917 uses->parent = parent;
2918
2919 /* parse substatements */
2920 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2921 switch (child->kw) {
2922 case LY_STMT_DESCRIPTION:
2923 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2924 break;
2925 case LY_STMT_IF_FEATURE:
2926 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2927 break;
2928 case LY_STMT_REFERENCE:
2929 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2930 break;
2931 case LY_STMT_STATUS:
2932 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2933 break;
2934 case LY_STMT_WHEN:
2935 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2936 break;
2937
2938 case LY_STMT_REFINE:
2939 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2940 break;
2941 case LY_STMT_AUGMENT:
2942 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2943 break;
2944 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002945 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002946 break;
2947 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002948 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002949 return LY_EVALID;
2950 }
2951 }
2952
2953 return LY_SUCCESS;
2954}
2955
2956/**
2957 * @brief Parse the case statement.
2958 *
2959 * @param[in] ctx parser context.
2960 * @param[in] stmt Source statement data from the parsed extension instance.
2961 * @param[in] parent Parent node to connect to (not into).
2962 * @param[in,out] siblings Siblings to add to.
2963 *
2964 * @return LY_ERR values.
2965 */
2966static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002967lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002968 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002969{
2970 struct lysp_node_case *cas;
2971
2972 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2973
2974 /* create new case structure */
2975 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2976
2977 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2978 cas->nodetype = LYS_CASE;
2979 cas->parent = parent;
2980
2981 /* parse substatements */
2982 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2983 switch (child->kw) {
2984 case LY_STMT_DESCRIPTION:
2985 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2986 break;
2987 case LY_STMT_IF_FEATURE:
2988 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2989 break;
2990 case LY_STMT_REFERENCE:
2991 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2992 break;
2993 case LY_STMT_STATUS:
2994 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2995 break;
2996 case LY_STMT_WHEN:
2997 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2998 break;
2999
3000 case LY_STMT_ANYDATA:
3001 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
3002 /* fall through */
3003 case LY_STMT_ANYXML:
3004 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
3005 break;
3006 case LY_STMT_CHOICE:
3007 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
3008 break;
3009 case LY_STMT_CONTAINER:
3010 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
3011 break;
3012 case LY_STMT_LEAF:
3013 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
3014 break;
3015 case LY_STMT_LEAF_LIST:
3016 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
3017 break;
3018 case LY_STMT_LIST:
3019 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
3020 break;
3021 case LY_STMT_USES:
3022 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
3023 break;
3024 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003025 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003026 break;
3027 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003028 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003029 return LY_EVALID;
3030 }
3031 }
3032 return LY_SUCCESS;
3033}
3034
3035/**
3036 * @brief Parse the choice statement.
3037 *
3038 * @param[in] ctx parser context.
3039 * @param[in] stmt Source statement data from the parsed extension instance.
3040 * @param[in] parent Parent node to connect to (not into).
3041 * @param[in,out] siblings Siblings to add to.
3042 *
3043 * @return LY_ERR values.
3044 */
3045static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003046lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003047 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003048{
3049 struct lysp_node_choice *choice;
3050
3051 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3052
3053 /* create new choice structure */
3054 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
3055
3056 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
3057 choice->nodetype = LYS_CHOICE;
3058 choice->parent = parent;
3059
3060 /* parse substatements */
3061 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3062 switch (child->kw) {
3063 case LY_STMT_CONFIG:
3064 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
3065 break;
3066 case LY_STMT_DESCRIPTION:
3067 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
3068 break;
3069 case LY_STMT_IF_FEATURE:
3070 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
3071 break;
3072 case LY_STMT_MANDATORY:
3073 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
3074 break;
3075 case LY_STMT_REFERENCE:
3076 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
3077 break;
3078 case LY_STMT_STATUS:
3079 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
3080 break;
3081 case LY_STMT_WHEN:
3082 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
3083 break;
3084 case LY_STMT_DEFAULT:
3085 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 +01003086 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003087 break;
3088 case LY_STMT_ANYDATA:
3089 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
3090 /* fall through */
3091 case LY_STMT_ANYXML:
3092 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
3093 break;
3094 case LY_STMT_CASE:
3095 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
3096 break;
3097 case LY_STMT_CHOICE:
3098 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
3099 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
3100 break;
3101 case LY_STMT_CONTAINER:
3102 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
3103 break;
3104 case LY_STMT_LEAF:
3105 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
3106 break;
3107 case LY_STMT_LEAF_LIST:
3108 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
3109 break;
3110 case LY_STMT_LIST:
3111 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
3112 break;
3113 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003114 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003115 break;
3116 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003117 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003118 return LY_EVALID;
3119 }
3120 }
3121 return LY_SUCCESS;
3122}
3123
3124/**
3125 * @brief Parse the container statement.
3126 *
3127 * @param[in] ctx parser context.
3128 * @param[in] stmt Source statement data from the parsed extension instance.
3129 * @param[in] parent Parent node to connect to (not into).
3130 * @param[in,out] siblings Siblings to add to.
3131 *
3132 * @return LY_ERR values.
3133 */
3134static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003135lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003136 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003137{
3138 struct lysp_node_container *cont;
3139
3140 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3141
3142 /* create new container structure */
3143 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
3144
3145 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
3146 cont->nodetype = LYS_CONTAINER;
3147 cont->parent = parent;
3148
3149 /* parse substatements */
3150 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3151 switch (child->kw) {
3152 case LY_STMT_CONFIG:
3153 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
3154 break;
3155 case LY_STMT_DESCRIPTION:
3156 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
3157 break;
3158 case LY_STMT_IF_FEATURE:
3159 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
3160 break;
3161 case LY_STMT_REFERENCE:
3162 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
3163 break;
3164 case LY_STMT_STATUS:
3165 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
3166 break;
3167 case LY_STMT_WHEN:
3168 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
3169 break;
3170 case LY_STMT_PRESENCE:
3171 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
3172 break;
3173 case LY_STMT_ANYDATA:
3174 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
3175 /* fall through */
3176 case LY_STMT_ANYXML:
3177 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
3178 break;
3179 case LY_STMT_CHOICE:
3180 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
3181 break;
3182 case LY_STMT_CONTAINER:
3183 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
3184 break;
3185 case LY_STMT_LEAF:
3186 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
3187 break;
3188 case LY_STMT_LEAF_LIST:
3189 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
3190 break;
3191 case LY_STMT_LIST:
3192 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
3193 break;
3194 case LY_STMT_USES:
3195 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
3196 break;
3197
3198 case LY_STMT_TYPEDEF:
3199 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
3200 break;
3201 case LY_STMT_MUST:
3202 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
3203 break;
3204 case LY_STMT_ACTION:
3205 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
3206 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
3207 break;
3208 case LY_STMT_GROUPING:
3209 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3210 break;
3211 case LY_STMT_NOTIFICATION:
3212 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3213 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3214 break;
3215 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003216 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003217 break;
3218 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003219 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003220 return LY_EVALID;
3221 }
3222 }
3223
3224 return LY_SUCCESS;
3225}
3226
3227/**
3228 * @brief Parse the list statement.
3229 *
3230 * @param[in] ctx parser context.
3231 * @param[in] stmt Source statement data from the parsed extension instance.
3232 * @param[in] parent Parent node to connect to (not into).
3233 * @param[in,out] siblings Siblings to add to.
3234 *
3235 * @return LY_ERR values.
3236 */
3237static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003238lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003239 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003240{
3241 struct lysp_node_list *list;
3242
3243 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3244
3245 /* create new list structure */
3246 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3247
3248 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3249 list->nodetype = LYS_LIST;
3250 list->parent = parent;
3251
3252 /* parse substatements */
3253 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3254 switch (child->kw) {
3255 case LY_STMT_CONFIG:
3256 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3257 break;
3258 case LY_STMT_DESCRIPTION:
3259 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3260 break;
3261 case LY_STMT_IF_FEATURE:
3262 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3263 break;
3264 case LY_STMT_REFERENCE:
3265 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3266 break;
3267 case LY_STMT_STATUS:
3268 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3269 break;
3270 case LY_STMT_WHEN:
3271 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3272 break;
3273 case LY_STMT_KEY:
3274 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3275 break;
3276 case LY_STMT_MAX_ELEMENTS:
3277 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3278 break;
3279 case LY_STMT_MIN_ELEMENTS:
3280 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3281 break;
3282 case LY_STMT_ORDERED_BY:
3283 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3284 break;
3285 case LY_STMT_UNIQUE:
3286 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3287 break;
3288
3289 case LY_STMT_ANYDATA:
3290 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3291 /* fall through */
3292 case LY_STMT_ANYXML:
3293 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3294 break;
3295 case LY_STMT_CHOICE:
3296 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3297 break;
3298 case LY_STMT_CONTAINER:
3299 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3300 break;
3301 case LY_STMT_LEAF:
3302 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3303 break;
3304 case LY_STMT_LEAF_LIST:
3305 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3306 break;
3307 case LY_STMT_LIST:
3308 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3309 break;
3310 case LY_STMT_USES:
3311 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3312 break;
3313
3314 case LY_STMT_TYPEDEF:
3315 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3316 break;
3317 case LY_STMT_MUST:
3318 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3319 break;
3320 case LY_STMT_ACTION:
3321 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3322 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3323 break;
3324 case LY_STMT_GROUPING:
3325 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3326 break;
3327 case LY_STMT_NOTIFICATION:
3328 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3329 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3330 break;
3331 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003332 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003333 break;
3334 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003335 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003336 return LY_EVALID;
3337 }
3338 }
3339
3340 return LY_SUCCESS;
3341}
3342
Michal Vasko193dacd2022-10-13 08:43:05 +02003343/**
3344 * @brief Parse generic statement structure into a specific parsed-schema structure.
3345 *
3346 * @param[in] pctx Parse context of the @p stmt being processed.
3347 * @param[in] stmt Generic statement structure to process.
3348 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3349 * @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.
3350 * @return LY_ERR value.
3351 */
3352static LY_ERR
3353lysp_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 +02003354{
Radek Krejciad5963b2019-09-06 16:03:05 +02003355 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003356 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003357
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003358 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003359 case LY_STMT_NOTIFICATION:
3360 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3361 break;
3362 case LY_STMT_INPUT:
3363 case LY_STMT_OUTPUT: {
3364 struct lysp_node_action_inout *inout;
3365
3366 *result = inout = calloc(1, sizeof *inout);
3367 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3368 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3369 break;
3370 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003371 case LY_STMT_ACTION:
3372 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003373 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003374 break;
3375 case LY_STMT_ANYDATA:
3376 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003377 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003378 break;
3379 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003380 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003381 break;
3382 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003383 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003384 break;
3385 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003386 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003387 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003388 case LY_STMT_CONTAINER:
3389 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003390 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003391 case LY_STMT_GROUPING:
3392 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3393 break;
3394 case LY_STMT_LEAF:
3395 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3396 break;
3397 case LY_STMT_LEAF_LIST:
3398 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3399 break;
3400 case LY_STMT_LIST:
3401 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3402 break;
3403 case LY_STMT_USES:
3404 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3405 break;
3406 case LY_STMT_BASE:
3407 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3408 break;
3409 case LY_STMT_ARGUMENT:
3410 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003411 case LY_STMT_CONTACT:
3412 case LY_STMT_DESCRIPTION:
3413 case LY_STMT_ERROR_APP_TAG:
3414 case LY_STMT_ERROR_MESSAGE:
3415 case LY_STMT_KEY:
3416 case LY_STMT_NAMESPACE:
3417 case LY_STMT_ORGANIZATION:
3418 case LY_STMT_PRESENCE:
3419 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003420 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003421 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003422 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003423 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003424 case LY_STMT_BIT:
3425 case LY_STMT_ENUM:
3426 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3427 break;
3428 case LY_STMT_CONFIG:
3429 assert(*result);
3430 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003431 break;
3432 case LY_STMT_DEFAULT:
3433 case LY_STMT_IF_FEATURE:
3434 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003435 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3436 break;
3437 case LY_STMT_DEVIATE:
3438 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3439 break;
3440 case LY_STMT_DEVIATION:
3441 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3442 break;
3443 case LY_STMT_EXTENSION:
3444 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003445 break;
3446 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003447 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3448 break;
3449 case LY_STMT_FEATURE:
3450 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003451 break;
3452 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003453 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003454 break;
3455 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003456 case LY_STMT_RANGE: {
3457 struct lysp_restr *restr;
3458
3459 *result = restr = calloc(1, sizeof *restr);
3460 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3461
3462 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003463 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003464 }
3465 case LY_STMT_MUST:
3466 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3467 break;
3468 case LY_STMT_IDENTITY:
3469 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3470 break;
3471 case LY_STMT_IMPORT:
3472 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3473 break;
3474 case LY_STMT_INCLUDE:
3475 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003476 break;
3477 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003478 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003479 break;
3480 case LY_STMT_MAX_ELEMENTS:
3481 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003482 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003483 break;
3484 case LY_STMT_MIN_ELEMENTS:
3485 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003486 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003487 break;
3488 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003489 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003490 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003491 case LY_STMT_MODULE: {
3492 struct lysp_module *mod;
3493
3494 *result = mod = calloc(1, sizeof *mod);
3495 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3496 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003497 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003498 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003499 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003500 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003501 break;
3502 case LY_STMT_PATH: {
3503 const char *str_path = NULL;
3504
Michal Vasko193dacd2022-10-13 08:43:05 +02003505 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3506 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003507 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003508 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003509 break;
3510 }
3511 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003512 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003513 break;
3514 case LY_STMT_POSITION:
3515 case LY_STMT_VALUE:
3516 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003517 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003518 break;
3519 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003520 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003521 break;
3522 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003523 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003524 break;
3525 case LY_STMT_REQUIRE_INSTANCE:
3526 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003527 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3528 break;
3529 case LY_STMT_REVISION:
3530 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003531 break;
Michal Vasko69730152020-10-09 16:30:07 +02003532 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003533 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003534 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003535 case LY_STMT_SUBMODULE: {
3536 struct lysp_submodule *submod;
3537
3538 *result = submod = calloc(1, sizeof *submod);
3539 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3540 ret = lysp_stmt_submodule(pctx, stmt, submod);
3541 break;
3542 }
Radek Krejci335332a2019-09-05 13:03:35 +02003543 case LY_STMT_TYPE: {
3544 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003545
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003546 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003547 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3548 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003549 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003550 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003551 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003552 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003553 break;
3554 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003555 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3556 break;
3557 case LY_STMT_YANG_VERSION:
3558 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3559 break;
3560 case LY_STMT_YIN_ELEMENT:
3561 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003562 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003563 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003564 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003565 return LY_EINT;
3566 }
3567
Radek Krejciad5963b2019-09-06 16:03:05 +02003568 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003569}
Michal Vasko59892dd2022-05-13 11:02:30 +02003570
Michal Vasko193dacd2022-10-13 08:43:05 +02003571LY_ERR
3572lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003573{
Michal Vasko193dacd2022-10-13 08:43:05 +02003574 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003575
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003576 if (!substmt->storage_p) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003577 /* nothing to parse, ignored */
3578 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003579 }
3580
Michal Vasko193dacd2022-10-13 08:43:05 +02003581 switch (stmt->kw) {
3582 case LY_STMT_NOTIFICATION:
3583 case LY_STMT_INPUT:
3584 case LY_STMT_OUTPUT:
3585 case LY_STMT_ACTION:
3586 case LY_STMT_RPC:
3587 case LY_STMT_ANYDATA:
3588 case LY_STMT_ANYXML:
3589 case LY_STMT_AUGMENT:
3590 case LY_STMT_CASE:
3591 case LY_STMT_CHOICE:
3592 case LY_STMT_CONTAINER:
3593 case LY_STMT_GROUPING:
3594 case LY_STMT_LEAF:
3595 case LY_STMT_LEAF_LIST:
3596 case LY_STMT_LIST:
3597 case LY_STMT_USES: {
3598 struct lysp_node **pnodes_p, *pnode = NULL;
3599
3600 /* parse the node */
3601 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3602
3603 /* usually is a linked-list of all the parsed schema nodes */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003604 pnodes_p = (struct lysp_node **)substmt->storage_p;
Michal Vasko193dacd2022-10-13 08:43:05 +02003605 while (*pnodes_p) {
3606 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003607 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003608 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003609
3610 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003611 }
3612 case LY_STMT_BASE:
3613 case LY_STMT_BIT:
3614 case LY_STMT_DEFAULT:
3615 case LY_STMT_DEVIATE:
3616 case LY_STMT_DEVIATION:
3617 case LY_STMT_ENUM:
3618 case LY_STMT_EXTENSION:
3619 case LY_STMT_EXTENSION_INSTANCE:
3620 case LY_STMT_FEATURE:
3621 case LY_STMT_IDENTITY:
3622 case LY_STMT_IF_FEATURE:
3623 case LY_STMT_IMPORT:
3624 case LY_STMT_INCLUDE:
3625 case LY_STMT_MUST:
3626 case LY_STMT_PATTERN:
3627 case LY_STMT_REFINE:
3628 case LY_STMT_REVISION:
3629 case LY_STMT_TYPEDEF:
3630 case LY_STMT_UNIQUE:
3631 /* parse, sized array */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003632 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003633 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003634
3635 case LY_STMT_ARGUMENT:
3636 case LY_STMT_BELONGS_TO:
3637 case LY_STMT_CONTACT:
3638 case LY_STMT_DESCRIPTION:
3639 case LY_STMT_ERROR_APP_TAG:
3640 case LY_STMT_ERROR_MESSAGE:
3641 case LY_STMT_FRACTION_DIGITS:
3642 case LY_STMT_KEY:
3643 case LY_STMT_LENGTH:
3644 case LY_STMT_MANDATORY:
3645 case LY_STMT_MAX_ELEMENTS:
3646 case LY_STMT_MIN_ELEMENTS:
3647 case LY_STMT_MODIFIER:
3648 case LY_STMT_MODULE:
3649 case LY_STMT_NAMESPACE:
3650 case LY_STMT_ORGANIZATION:
3651 case LY_STMT_PATH:
3652 case LY_STMT_POSITION:
3653 case LY_STMT_PREFIX:
3654 case LY_STMT_PRESENCE:
3655 case LY_STMT_RANGE:
3656 case LY_STMT_REFERENCE:
3657 case LY_STMT_REQUIRE_INSTANCE:
3658 case LY_STMT_REVISION_DATE:
3659 case LY_STMT_SUBMODULE:
3660 case LY_STMT_TYPE:
3661 case LY_STMT_UNITS:
3662 case LY_STMT_VALUE:
3663 case LY_STMT_WHEN:
3664 case LY_STMT_YANG_VERSION:
3665 case LY_STMT_YIN_ELEMENT:
3666 /* single item */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003667 if (*substmt->storage_p) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003668 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3669 rc = LY_EVALID;
3670 goto cleanup;
3671 }
3672
3673 /* parse */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003674 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003675 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003676
3677 case LY_STMT_CONFIG:
3678 /* single item */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003679 if ((*(uint16_t *)substmt->storage_p) & LYS_CONFIG_MASK) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003680 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3681 rc = LY_EVALID;
3682 goto cleanup;
3683 }
3684
3685 /* parse */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003686 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +02003687 break;
3688
3689 case LY_STMT_ORDERED_BY:
3690 /* single item */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003691 if ((*(uint16_t *)substmt->storage_p) & LYS_ORDBY_MASK) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003692 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3693 rc = LY_EVALID;
3694 goto cleanup;
3695 }
3696
3697 /* parse */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003698 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +02003699 break;
3700
3701 case LY_STMT_STATUS:
3702 /* single item */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003703 if ((*(uint16_t *)substmt->storage_p) & LYS_STATUS_MASK) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003704 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3705 rc = LY_EVALID;
3706 goto cleanup;
3707 }
3708
3709 /* parse */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +02003710 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage_p, NULL), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +02003711 break;
3712
Michal Vasko59892dd2022-05-13 11:02:30 +02003713 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003714 LOGINT(PARSER_CTX(pctx));
3715 rc = LY_EINT;
3716 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003717 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003718
3719cleanup:
3720 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003721}