blob: dadd1d7adc8e6e6567cac164113316d61634e373 [file] [log] [blame]
Radek Krejci335332a2019-09-05 13:03:35 +02001/**
Michal Vasko59892dd2022-05-13 11:02:30 +02002 * @file parser_common.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief libyang common parser functions.
Radek Krejci335332a2019-09-05 13:03:35 +02005 *
Michal Vasko59892dd2022-05-13 11:02:30 +02006 * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
Radek Krejci335332a2019-09-05 13:03:35 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Michal Vasko59892dd2022-05-13 11:02:30 +020015#define _GNU_SOURCE
16#define _POSIX_C_SOURCE 200809L /* strdup, strndup */
17
18#ifdef __APPLE__
19#define _DARWIN_C_SOURCE /* F_GETPATH */
20#endif
21
22#if defined (__NetBSD__) || defined (__OpenBSD__)
23/* realpath */
24#define _XOPEN_SOURCE 1
25#define _XOPEN_SOURCE_EXTENDED 1
26#endif
27
28#include "parser_internal.h"
29
Radek Krejci335332a2019-09-05 13:03:35 +020030#include <assert.h>
31#include <ctype.h>
32#include <errno.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020033#include <fcntl.h>
34#include <limits.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020035#include <stdint.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020036#include <stdio.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020037#include <stdlib.h>
38#include <string.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020039#include <unistd.h>
Radek Krejci335332a2019-09-05 13:03:35 +020040
Michal Vasko59892dd2022-05-13 11:02:30 +020041#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020042#include "dict.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020043#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010044#include "log.h"
Michal Vasko8f702ee2024-02-20 15:44:24 +010045#include "ly_common.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020046#include "parser_data.h"
Michal Vasko69730152020-10-09 16:30:07 +020047#include "path.h"
Michal Vaskob4750962022-10-06 15:33:35 +020048#include "plugins_exts/metadata.h"
Michal Vasko820efe82023-05-12 15:47:43 +020049#include "schema_compile_node.h"
Michal Vasko193dacd2022-10-13 08:43:05 +020050#include "schema_features.h"
Radek Krejci77114102021-03-10 15:21:57 +010051#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020052#include "tree.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020053#include "tree_data.h"
54#include "tree_data_internal.h"
Radek Krejci335332a2019-09-05 13:03:35 +020055#include "tree_schema.h"
56#include "tree_schema_internal.h"
57
Michal Vasko59892dd2022-05-13 11:02:30 +020058void
59lyd_ctx_free(struct lyd_ctx *lydctx)
60{
61 ly_set_erase(&lydctx->node_types, NULL);
62 ly_set_erase(&lydctx->meta_types, NULL);
63 ly_set_erase(&lydctx->node_when, NULL);
Michal Vasko135719f2022-08-25 12:18:17 +020064 ly_set_erase(&lydctx->ext_node, free);
Michal Vasko59892dd2022-05-13 11:02:30 +020065 ly_set_erase(&lydctx->ext_val, free);
66}
67
68LY_ERR
Michal Vasko820efe82023-05-12 15:47:43 +020069lyd_parser_notif_eventtime_validate(const struct lyd_node *node)
70{
71 LY_ERR rc = LY_SUCCESS;
72 struct ly_ctx *ctx = (struct ly_ctx *)LYD_CTX(node);
73 struct lysc_ctx cctx;
74 const struct lys_module *mod;
75 LY_ARRAY_COUNT_TYPE u;
76 struct ly_err_item *err = NULL;
77 struct lysp_type *type_p = NULL;
78 struct lysc_pattern **patterns = NULL;
79 const char *value;
80
81 LYSC_CTX_INIT_CTX(cctx, ctx);
82
83 /* get date-and-time parsed type */
84 mod = ly_ctx_get_module_latest(ctx, "ietf-yang-types");
85 assert(mod);
86 LY_ARRAY_FOR(mod->parsed->typedefs, u) {
87 if (!strcmp(mod->parsed->typedefs[u].name, "date-and-time")) {
88 type_p = &mod->parsed->typedefs[u].type;
89 break;
90 }
91 }
92 assert(type_p);
93
94 /* compile patterns */
95 assert(type_p->patterns);
96 LY_CHECK_GOTO(rc = lys_compile_type_patterns(&cctx, type_p->patterns, NULL, &patterns), cleanup);
97
98 /* validate */
99 value = lyd_get_value(node);
100 rc = lyplg_type_validate_patterns(patterns, value, strlen(value), &err);
101
102cleanup:
103 FREE_ARRAY(&cctx.free_ctx, patterns, lysc_pattern_free);
104 if (rc && err) {
Michal Vasko7a266772024-01-23 11:02:38 +0100105 ly_err_print(ctx, err);
Michal Vasko820efe82023-05-12 15:47:43 +0200106 ly_err_free(err);
107 LOGVAL(ctx, LYVE_DATA, "Invalid \"eventTime\" in the notification.");
108 }
109 return rc;
110}
111
112LY_ERR
Michal Vasko59892dd2022-05-13 11:02:30 +0200113lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op)
114{
115 const struct lyd_node *iter;
116
117 *op = NULL;
118
119 if (!parent) {
120 /* no parent, nothing to look for */
121 return LY_SUCCESS;
122 }
123
124 /* we need to find the operation node if it already exists */
125 for (iter = parent; iter; iter = lyd_parent(iter)) {
126 if (iter->schema && (iter->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
127 break;
128 }
129 }
130
131 if (!iter) {
132 /* no operation found */
133 return LY_SUCCESS;
134 }
135
Michal Vaskoe3ed7dc2022-11-30 11:39:44 +0100136 if (!(int_opts & LYD_INTOPT_ANY)) {
137 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
138 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
139 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
140 return LY_EINVAL;
141 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
142 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
143 iter->schema->name);
144 return LY_EINVAL;
145 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
146 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
147 iter->schema->name);
148 return LY_EINVAL;
149 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
150 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
151 iter->schema->name);
152 return LY_EINVAL;
153 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200154 }
155
156 *op = (struct lyd_node *)iter;
157 return LY_SUCCESS;
158}
159
Michal Vaskoa878a892023-08-18 12:22:07 +0200160const struct lysc_node *
161lyd_parser_node_schema(const struct lyd_node *node)
162{
163 uint32_t i;
164 const struct lyd_node *iter;
165 const struct lysc_node *schema = NULL;
166 const struct lys_module *mod;
167
168 if (!node) {
169 return NULL;
170 } else if (node->schema) {
171 /* simplest case */
172 return node->schema;
173 }
174
175 /* find the first schema node in the parsed nodes */
176 i = ly_log_location_dnode_count();
177 if (i) {
178 do {
179 --i;
180 if (ly_log_location_dnode(i)->schema) {
181 /* this node is processed */
182 schema = ly_log_location_dnode(i)->schema;
183 ++i;
184 break;
185 }
186 } while (i);
187 }
188
189 /* get schema node of an opaque node */
190 do {
191 /* get next data node */
192 if (i == ly_log_location_dnode_count()) {
193 iter = node;
194 } else {
195 iter = ly_log_location_dnode(i);
196 }
197 assert(!iter->schema);
198
199 /* get module */
Michal Vasko420cc252023-08-24 08:14:24 +0200200 mod = lyd_node_module(iter);
Michal Vaskoa878a892023-08-18 12:22:07 +0200201 if (!mod) {
202 /* unknown module, no schema node */
203 schema = NULL;
204 break;
205 }
206
207 /* get schema node */
208 schema = lys_find_child(schema, mod, LYD_NAME(iter), 0, 0, 0);
209
210 /* move to the descendant */
211 ++i;
212 } while (schema && (iter != node));
213
214 return schema;
215}
216
Michal Vasko59892dd2022-05-13 11:02:30 +0200217LY_ERR
218lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
219{
220 LY_ERR rc = LY_SUCCESS;
221
Michal Vasko7a266772024-01-23 11:02:38 +0100222 LOG_LOCSET(snode, NULL);
Michal Vasko59892dd2022-05-13 11:02:30 +0200223
224 if (lydctx->int_opts & LYD_INTOPT_ANY) {
225 /* nothing to check, everything is allowed */
226 goto cleanup;
227 }
228
229 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
230 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
231 rc = LY_EVALID;
232 goto cleanup;
233 }
234
235 if (snode->nodetype == LYS_RPC) {
236 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
237 if (lydctx->op_node) {
238 goto error_node_dup;
239 }
240 } else {
241 goto error_node_inval;
242 }
243 } else if (snode->nodetype == LYS_ACTION) {
244 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
245 if (lydctx->op_node) {
246 goto error_node_dup;
247 }
248 } else {
249 goto error_node_inval;
250 }
251 } else if (snode->nodetype == LYS_NOTIF) {
252 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
253 if (lydctx->op_node) {
254 goto error_node_dup;
255 }
256 } else {
257 goto error_node_inval;
258 }
259 }
260
261 /* success */
262 goto cleanup;
263
264error_node_dup:
265 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
266 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
267 lydctx->op_node->schema->name);
268 rc = LY_EVALID;
269 goto cleanup;
270
271error_node_inval:
272 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
273 snode->name);
274 rc = LY_EVALID;
275
276cleanup:
Michal Vasko7a266772024-01-23 11:02:38 +0100277 LOG_LOCBACK(1, 0);
Michal Vasko59892dd2022-05-13 11:02:30 +0200278 return rc;
279}
280
281LY_ERR
282lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
283 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
284{
Michal Vasko9dbb91d2023-01-30 13:59:22 +0100285 LY_ERR r;
Michal Vasko59892dd2022-05-13 11:02:30 +0200286 ly_bool incomplete;
287
Michal Vasko989cdb42023-10-06 15:32:37 +0200288 if ((r = lyd_create_term(schema, value, value_len, 1, dynamic, format, prefix_data, hints, &incomplete, node))) {
Michal Vasko9dbb91d2023-01-30 13:59:22 +0100289 if (lydctx->data_ctx->ctx != schema->module->ctx) {
290 /* move errors to the main context */
291 ly_err_move(schema->module->ctx, (struct ly_ctx *)lydctx->data_ctx->ctx);
292 }
293 return r;
294 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200295
296 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
297 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
298 }
299 return LY_SUCCESS;
300}
301
302LY_ERR
303lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
304 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
305 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
306{
Michal Vaskodd03ff12023-09-11 10:30:48 +0200307 LY_ERR rc = LY_SUCCESS;
308 char *dpath = NULL, *path = NULL;
Michal Vasko59892dd2022-05-13 11:02:30 +0200309 ly_bool incomplete;
310 struct lyd_meta *first = NULL;
311
312 if (meta && *meta) {
313 /* remember the first metadata */
314 first = *meta;
315 }
316
Michal Vaskodd03ff12023-09-11 10:30:48 +0200317 /* generate path to the metadata */
318 LY_CHECK_RET(ly_vlog_build_data_path(lydctx->data_ctx->ctx, &dpath));
319 if (asprintf(&path, "%s/@%s:%.*s", dpath, mod->name, (int)name_len, name) == -1) {
320 LOGMEM(lydctx->data_ctx->ctx);
321 rc = LY_EMEM;
322 goto cleanup;
323 }
Michal Vasko7a266772024-01-23 11:02:38 +0100324 ly_log_location(NULL, NULL, path, NULL);
Michal Vaskodd03ff12023-09-11 10:30:48 +0200325
Michal Vasko989cdb42023-10-06 15:32:37 +0200326 LY_CHECK_GOTO(rc = lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, 1, dynamic, format,
327 prefix_data, hints, ctx_node, 0, &incomplete), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +0200328
329 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
Michal Vaskodd03ff12023-09-11 10:30:48 +0200330 LY_CHECK_GOTO(rc = ly_set_add(&lydctx->meta_types, *meta, 1, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +0200331 }
332
333 if (first) {
334 /* always return the first metadata */
335 *meta = first;
336 }
337
Michal Vaskodd03ff12023-09-11 10:30:48 +0200338cleanup:
Michal Vasko7a266772024-01-23 11:02:38 +0100339 ly_log_location_revert(0, 0, 1, 0);
Michal Vaskodd03ff12023-09-11 10:30:48 +0200340 free(dpath);
341 free(path);
342 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +0200343}
344
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200345LY_ERR
346lyd_parse_check_keys(struct lyd_node *node)
347{
348 const struct lysc_node *skey = NULL;
349 const struct lyd_node *key;
350
351 assert(node->schema->nodetype == LYS_LIST);
352
353 key = lyd_child(node);
354 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
355 if (!key || (key->schema != skey)) {
356 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
357 return LY_EVALID;
358 }
359
360 key = key->next;
361 }
362
363 return LY_SUCCESS;
364}
365
366LY_ERR
367lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
368 struct lysc_ext_instance *ext)
369{
aPieceked39cbe2023-11-06 14:20:27 +0100370 struct lyd_meta *meta2, *prev_meta = NULL, *next_meta = NULL;
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200371 struct lyd_ctx_ext_val *ext_val;
372
Michal Vaskobc9f76f2022-12-01 10:31:38 +0100373 if (lydctx->parse_opts & LYD_PARSE_NO_NEW) {
374 node->flags &= ~LYD_NEW;
375 }
376
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200377 if (lysc_has_when(node->schema)) {
Michal Vaskofbb48c22022-11-30 13:28:03 +0100378 if (lydctx->parse_opts & LYD_PARSE_WHEN_TRUE) {
379 /* the condition was true before */
380 node->flags |= LYD_WHEN_TRUE;
381 }
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200382 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
383 /* remember we need to evaluate this node's when */
384 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
385 }
386 }
387
388 LY_LIST_FOR(*meta, meta2) {
389 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
390 meta2->value.boolean) {
391 /* node is default according to the metadata */
392 node->flags |= LYD_DEFAULT;
393
aPieceked39cbe2023-11-06 14:20:27 +0100394 next_meta = meta2->next;
395
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200396 /* delete the metadata */
aPieceked39cbe2023-11-06 14:20:27 +0100397 if (meta != &node->meta) {
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200398 *meta = (*meta)->next;
399 }
400 lyd_free_meta_single(meta2);
aPieceked39cbe2023-11-06 14:20:27 +0100401 if (prev_meta) {
402 prev_meta->next = next_meta;
403 }
Michal Vasko4754d4a2022-12-01 10:11:21 +0100404
405 /* update dflt flag for all parent NP containers */
406 lyd_cont_set_dflt(lyd_parent(node));
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200407 break;
408 }
409
410 prev_meta = meta2;
411 }
412
413 if (ext) {
414 /* parsed for an extension */
415 node->flags |= LYD_EXT;
416
417 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
418 /* rememeber for validation */
419 ext_val = malloc(sizeof *ext_val);
420 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
421 ext_val->ext = ext;
422 ext_val->sibling = node;
423 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
424 }
425 }
426
427 return LY_SUCCESS;
428}
429
Michal Vasko193dacd2022-10-13 08:43:05 +0200430void
431lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
432{
433 char path[PATH_MAX];
434
435#ifndef __APPLE__
436 char proc_path[32];
437 int len;
438#endif
439
440 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
441 if (*filepath) {
442 /* filepath already set */
443 return;
444 }
445
446 switch (in->type) {
447 case LY_IN_FILEPATH:
448 if (realpath(in->method.fpath.filepath, path) != NULL) {
449 lydict_insert(ctx, path, 0, filepath);
450 } else {
451 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
452 }
453
454 break;
455 case LY_IN_FD:
456#ifdef __APPLE__
457 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
458 lydict_insert(ctx, path, 0, filepath);
459 }
460#elif defined _WIN32
461 HANDLE h = _get_osfhandle(in->method.fd);
462 FILE_NAME_INFO info;
Michal Vasko2bf4af42023-01-04 12:08:38 +0100463
Michal Vasko193dacd2022-10-13 08:43:05 +0200464 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
465 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
Michal Vasko2bf4af42023-01-04 12:08:38 +0100466
Michal Vasko193dacd2022-10-13 08:43:05 +0200467 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
468 lydict_insert(ctx, buf, len, filepath);
469 }
470#else
471 /* get URI if there is /proc */
472 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
473 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
474 lydict_insert(ctx, path, len, filepath);
475 }
476#endif
477 break;
478 case LY_IN_MEMORY:
479 case LY_IN_FILE:
480 /* nothing to do */
481 break;
482 default:
483 LOGINT(ctx);
484 break;
485 }
486}
487
Michal Vaskod0625d72022-10-06 15:02:50 +0200488static 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 +0100489 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200490static 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 +0100491 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200492static 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 +0100493 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200494static 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 +0100495 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200496static 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 +0100497 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200498static 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 +0100499 struct lysp_node **siblings);
500
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100501/**
502 * @brief Validate stmt string value.
503 *
504 * @param[in] ctx Parser context.
505 * @param[in] val_type String value type.
506 * @param[in] val Value to validate.
507 * @return LY_ERR value.
508 */
Radek Krejci335332a2019-09-05 13:03:35 +0200509static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200510lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200511{
Radek Krejci857189e2020-09-01 13:26:36 +0200512 uint8_t prefix = 0;
513 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200514 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200515 size_t utf8_char_len;
516
Michal Vaskocfa1a962023-02-27 09:28:45 +0100517 if (!val) {
518 if (val_type == Y_MAYBE_STR_ARG) {
519 /* fine */
520 return LY_SUCCESS;
521 }
522
523 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Missing an expected string.");
524 return LY_EVALID;
525 }
526
Radek Krejci335332a2019-09-05 13:03:35 +0200527 while (*val) {
528 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200529 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200530
531 switch (val_type) {
532 case Y_IDENTIF_ARG:
533 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
534 break;
535 case Y_PREF_IDENTIF_ARG:
536 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
537 break;
538 case Y_STR_ARG:
539 case Y_MAYBE_STR_ARG:
540 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
541 break;
542 }
543 first = 0;
544 }
545
546 return LY_SUCCESS;
547}
548
549/**
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100550 * @brief Duplicate statement siblings, recursively.
551 *
552 * @param[in] ctx Parser context.
553 * @param[in] stmt Statement to duplicate.
554 * @param[out] first First duplicated statement, the rest follow.
555 * @return LY_ERR value.
556 */
557static LY_ERR
558lysp_stmt_dup(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_stmt **first)
559{
560 struct lysp_stmt *child, *last = NULL;
561
562 LY_LIST_FOR(stmt, stmt) {
563 child = calloc(1, sizeof *child);
564 LY_CHECK_ERR_RET(!child, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
565
566 if (last) {
567 last->next = child;
568 } else {
569 assert(!*first);
570 *first = child;
571 }
572 last = child;
573
574 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &child->stmt));
575 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &child->arg));
576 child->format = stmt->format;
577 LY_CHECK_RET(ly_dup_prefix_data(PARSER_CTX(ctx), stmt->format, stmt->prefix_data, &child->prefix_data));
578 child->flags = stmt->flags;
579 child->kw = stmt->kw;
580
581 /* recursively */
582 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &child->child));
583 }
584
585 return LY_SUCCESS;
586}
587
588/**
Radek Krejci335332a2019-09-05 13:03:35 +0200589 * @brief Parse extension instance.
590 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100591 * @param[in] ctx parser context.
592 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100593 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200594 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
595 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200596 * @return LY_ERR values.
597 */
598static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200599lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200600 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200601{
602 struct lysp_ext_instance *e;
603
Michal Vaskob36053d2020-03-26 15:49:30 +0100604 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200605
606 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200607 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100608 e->parent_stmt = insubstmt;
609 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200610 e->parsed = NULL;
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100611 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &e->child));
Radek Krejci335332a2019-09-05 13:03:35 +0200612
613 /* get optional argument */
614 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200615 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200616 }
617
618 return LY_SUCCESS;
619}
620
621/**
622 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
623 * description, etc...
624 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100625 * @param[in] ctx parser context.
626 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200627 * @param[in] substmt_index Index of this substatement.
628 * @param[in,out] value Place to store the parsed value.
629 * @param[in] arg Type of the YANG keyword argument (of the value).
630 * @param[in,out] exts Extension instances to add to.
631 *
632 * @return LY_ERR values.
633 */
634static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200635lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
636 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200637{
Radek Krejci335332a2019-09-05 13:03:35 +0200638 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200639 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200640 return LY_EVALID;
641 }
642
643 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200644 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200645
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100646 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
647 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200648 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100649 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200650 break;
651 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200652 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200653 return LY_EVALID;
654 }
655 }
656 return LY_SUCCESS;
657}
658
659/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200660 * @brief Parse a qname that can have more instances such as if-feature.
661 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100662 * @param[in] ctx parser context.
663 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200664 * @param[in,out] qnames Parsed qnames to add to.
665 * @param[in] arg Type of the expected argument.
666 * @param[in,out] exts Extension instances to add to.
667 *
668 * @return LY_ERR values.
669 */
670static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200671lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
672 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200673{
674 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200675
676 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
677
678 /* allocate new pointer */
679 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
680 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100681 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200682
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100683 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
684 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200685 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100686 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200687 break;
688 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200689 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200690 return LY_EVALID;
691 }
692 }
693 return LY_SUCCESS;
694}
695
696/**
Radek Krejci335332a2019-09-05 13:03:35 +0200697 * @brief Parse a generic text field that can have more instances such as base.
698 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100699 * @param[in] ctx parser context.
700 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200701 * @param[in,out] texts Parsed values to add to.
702 * @param[in] arg Type of the expected argument.
703 * @param[in,out] exts Extension instances to add to.
704 *
705 * @return LY_ERR values.
706 */
707static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200708lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
709 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200710{
711 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200712
713 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
714
715 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100716 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200717 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200718
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100719 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
720 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200721 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100722 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200723 break;
724 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200725 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200726 return LY_EVALID;
727 }
728 }
729 return LY_SUCCESS;
730}
731
732/**
733 * @brief Parse the status statement.
734 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100735 * @param[in] ctx parser context.
736 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200737 * @param[in,out] flags Flags to add to.
738 * @param[in,out] exts Extension instances to add to.
739 *
740 * @return LY_ERR values.
741 */
742static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200743lysp_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 +0200744{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200745 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200746
747 if (*flags & LYS_STATUS_MASK) {
748 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
749 return LY_EVALID;
750 }
751
752 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
753 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100754 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200755 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100756 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200757 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100758 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200759 *flags |= LYS_STATUS_OBSLT;
760 } else {
761 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
762 return LY_EVALID;
763 }
764
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100765 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
766 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200767 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100768 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200769 break;
770 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200771 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200772 return LY_EVALID;
773 }
774 }
775 return LY_SUCCESS;
776}
777
778/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100779 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200780 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100781 * @param[in] ctx parser context.
782 * @param[in] stmt Source statement data from the parsed extension instance.
783 * @param[in,out] when_p When pointer to parse to.
784 *
785 * @return LY_ERR values.
786 */
787static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200788lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100789{
790 LY_ERR ret = LY_SUCCESS;
791 struct lysp_when *when;
792
793 if (*when_p) {
794 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
795 return LY_EVALID;
796 }
797
798 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
799
800 when = calloc(1, sizeof *when);
801 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
802 *when_p = when;
803
804 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
805
806 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
807 switch (child->kw) {
808 case LY_STMT_DESCRIPTION:
809 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
810 break;
811 case LY_STMT_REFERENCE:
812 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
813 break;
814 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100815 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100816 break;
817 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200818 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100819 return LY_EVALID;
820 }
821 }
822 return ret;
823}
824
825/**
826 * @brief Parse the config statement.
827 *
828 * @param[in] ctx parser context.
829 * @param[in] stmt Source statement data from the parsed extension instance.
830 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200831 * @param[in,out] exts Extension instances to add to.
832 *
833 * @return LY_ERR values.
834 */
835static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200836lysp_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 +0200837{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200838 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200839
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100840 if (*flags & LYS_CONFIG_MASK) {
841 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
842 return LY_EVALID;
843 }
844
845 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
846 arg_len = strlen(stmt->arg);
847 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
848 *flags |= LYS_CONFIG_W;
849 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
850 *flags |= LYS_CONFIG_R;
851 } else {
852 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
853 return LY_EVALID;
854 }
855
856 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
857 switch (child->kw) {
858 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100859 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100860 break;
861 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200862 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100863 return LY_EVALID;
864 }
865 }
866
867 return LY_SUCCESS;
868}
869
870/**
871 * @brief Parse the mandatory statement.
872 *
873 * @param[in] ctx parser context.
874 * @param[in] stmt Source statement data from the parsed extension instance.
875 * @param[in,out] flags Flags to add to.
876 * @param[in,out] exts Extension instances to add to.
877 *
878 * @return LY_ERR values.
879 */
880static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200881lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200882 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100883{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200884 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100885
886 if (*flags & LYS_MAND_MASK) {
887 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
888 return LY_EVALID;
889 }
890
891 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
892 arg_len = strlen(stmt->arg);
893 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
894 *flags |= LYS_MAND_TRUE;
895 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
896 *flags |= LYS_MAND_FALSE;
897 } else {
898 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
899 return LY_EVALID;
900 }
901
902 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
903 switch (child->kw) {
904 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100905 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100906 break;
907 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200908 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100909 return LY_EVALID;
910 }
911 }
912
913 return LY_SUCCESS;
914}
915
916/**
917 * @brief Parse a restriction such as range or length.
918 *
919 * @param[in] ctx parser context.
920 * @param[in] stmt Source statement data from the parsed extension instance.
921 * @param[in,out] exts Extension instances to add to.
922 *
923 * @return LY_ERR values.
924 */
925static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200926lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100927{
Radek Krejci335332a2019-09-05 13:03:35 +0200928 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200929 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100930 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200931
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100932 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
933 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200934 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100935 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200936 break;
937 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100938 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200939 break;
940 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100941 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200942 break;
943 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100944 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200945 break;
946 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100947 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200948 break;
949 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200950 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200951 return LY_EVALID;
952 }
953 }
954 return LY_SUCCESS;
955}
956
957/**
958 * @brief Parse a restriction that can have more instances such as must.
959 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100960 * @param[in] ctx parser context.
961 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200962 * @param[in,out] restrs Restrictions to add to.
963 *
964 * @return LY_ERR values.
965 */
966static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200967lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200968{
969 struct lysp_restr *restr;
970
Michal Vaskob36053d2020-03-26 15:49:30 +0100971 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100972 return lysp_stmt_restr(ctx, stmt, restr);
973}
974
975/**
976 * @brief Parse the anydata or anyxml statement.
977 *
978 * @param[in] ctx parser context.
979 * @param[in] stmt Source statement data from the parsed extension instance.
980 * @param[in,out] siblings Siblings to add to.
981 *
982 * @return LY_ERR values.
983 */
984static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200985lysp_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 +0100986{
987 struct lysp_node_anydata *any;
988
989 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
990
991 /* create new structure and insert into siblings */
992 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
993
994 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
995 any->parent = parent;
996
997 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
998
999 /* parse substatements */
1000 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1001 switch (child->kw) {
1002 case LY_STMT_CONFIG:
1003 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
1004 break;
1005 case LY_STMT_DESCRIPTION:
1006 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
1007 break;
1008 case LY_STMT_IF_FEATURE:
1009 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
1010 break;
1011 case LY_STMT_MANDATORY:
1012 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
1013 break;
1014 case LY_STMT_MUST:
1015 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
1016 break;
1017 case LY_STMT_REFERENCE:
1018 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
1019 break;
1020 case LY_STMT_STATUS:
1021 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
1022 break;
1023 case LY_STMT_WHEN:
1024 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
1025 break;
1026 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001027 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001028 break;
1029 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001030 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1031 (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 +01001032 return LY_EVALID;
1033 }
1034 }
1035
1036 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +02001037}
1038
1039/**
1040 * @brief Parse the value or position statement. Substatement of type enum statement.
1041 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001042 * @param[in] ctx parser context.
1043 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001044 * @param[in,out] value Value to write to.
1045 * @param[in,out] flags Flags to write to.
1046 * @param[in,out] exts Extension instances to add to.
1047 *
1048 * @return LY_ERR values.
1049 */
1050static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001051lysp_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 +02001052 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001053{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001054 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001055 char *ptr = NULL;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001056 long long num = 0;
1057 unsigned long long unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +02001058
1059 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001060 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001061 return LY_EVALID;
1062 }
1063 *flags |= LYS_SET_VALUE;
1064
1065 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1066
1067 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001068 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
1069 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001070 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001071 goto error;
1072 }
1073
1074 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001075 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001076 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001077 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001078 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001079 goto error;
1080 }
1081 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001082 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001083 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001084 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001085 goto error;
1086 }
1087 }
1088 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001089 if (ptr - stmt->arg != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001090 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001091 goto error;
1092 }
1093 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001094 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001095 goto error;
1096 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001097 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +02001098 *value = num;
1099 } else {
1100 *value = unum;
1101 }
1102
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001103 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1104 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001105 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001106 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 +02001107 break;
1108 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001109 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001110 return LY_EVALID;
1111 }
1112 }
1113 return LY_SUCCESS;
1114
1115error:
1116 return LY_EVALID;
1117}
1118
1119/**
1120 * @brief Parse the enum or bit statement. Substatement of type statement.
1121 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001122 * @param[in] ctx parser context.
1123 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001124 * @param[in,out] enums Enums or bits to add to.
1125 *
1126 * @return LY_ERR values.
1127 */
1128static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001129lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +02001130{
1131 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +02001132
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001133 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 +02001134
Michal Vaskob36053d2020-03-26 15:49:30 +01001135 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001136
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001137 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +02001138 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
1139 } /* else nothing specific for YANG_BIT */
1140
Radek Krejci011e4aa2020-09-04 15:22:31 +02001141 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +02001142 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +02001143
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001144 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1145 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001146 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001147 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001148 break;
1149 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001150 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001151 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001152 break;
1153 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001154 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001155 break;
1156 case LY_STMT_STATUS:
1157 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
1158 break;
1159 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001160 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1161 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001162 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001163 break;
1164 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +02001165 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1166 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001167 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001168 break;
1169 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001170 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001171 break;
1172 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001173 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001174 return LY_EVALID;
1175 }
1176 }
Michal Vasko193dacd2022-10-13 08:43:05 +02001177
Radek Krejci335332a2019-09-05 13:03:35 +02001178 return LY_SUCCESS;
1179}
1180
1181/**
1182 * @brief Parse the fraction-digits statement. Substatement of type statement.
1183 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001184 * @param[in] ctx parser context.
1185 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001186 * @param[in,out] fracdig Value to write to.
1187 * @param[in,out] exts Extension instances to add to.
1188 *
1189 * @return LY_ERR values.
1190 */
1191static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001192lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001193 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001194{
1195 char *ptr;
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001196 int arg_len;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001197 unsigned long long num;
Radek Krejci335332a2019-09-05 13:03:35 +02001198
1199 if (*fracdig) {
1200 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1201 return LY_EVALID;
1202 }
1203
1204 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1205 arg_len = strlen(stmt->arg);
1206 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1207 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1208 return LY_EVALID;
1209 }
1210
1211 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001212 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001213 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001214 if (ptr - stmt->arg != arg_len) {
Radek Krejci335332a2019-09-05 13:03:35 +02001215 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1216 return LY_EVALID;
1217 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001218 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001219 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1220 return LY_EVALID;
1221 }
1222 *fracdig = num;
1223
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001224 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1225 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001226 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001227 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001228 break;
1229 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001230 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001231 return LY_EVALID;
1232 }
1233 }
1234 return LY_SUCCESS;
1235}
1236
1237/**
1238 * @brief Parse the require-instance statement. Substatement of type statement.
1239 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001240 * @param[in] ctx parser context.
1241 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001242 * @param[in,out] reqinst Value to write to.
1243 * @param[in,out] flags Flags to write to.
1244 * @param[in,out] exts Extension instances to add to.
1245 *
1246 * @return LY_ERR values.
1247 */
1248static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001249lysp_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 +02001250 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001251{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001252 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001253
1254 if (*flags & LYS_SET_REQINST) {
1255 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1256 return LY_EVALID;
1257 }
1258 *flags |= LYS_SET_REQINST;
1259
1260 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1261 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001262 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001263 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001264 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001265 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1266 return LY_EVALID;
1267 }
1268
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001269 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1270 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001271 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001272 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001273 break;
1274 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001275 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001276 return LY_EVALID;
1277 }
1278 }
1279 return LY_SUCCESS;
1280}
1281
1282/**
1283 * @brief Parse the modifier statement. Substatement of type pattern statement.
1284 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001285 * @param[in] ctx parser context.
1286 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001287 * @param[in,out] pat Value to write to.
1288 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001289 * @return LY_ERR values.
1290 */
1291static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001292lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001293 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001294{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001295 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001296 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001297
Radek Krejcif13b87b2020-12-01 22:02:17 +01001298 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001299 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1300 return LY_EVALID;
1301 }
1302
1303 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1304 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001305 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001306 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1307 return LY_EVALID;
1308 }
1309
1310 /* replace the value in the dictionary */
1311 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001312 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001313 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001314 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001315
Radek Krejcif13b87b2020-12-01 22:02:17 +01001316 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1317 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001318 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001319
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001320 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1321 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001322 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001323 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001324 break;
1325 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001326 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001327 return LY_EVALID;
1328 }
1329 }
1330 return LY_SUCCESS;
1331}
1332
1333/**
1334 * @brief Parse the pattern statement. Substatement of type statement.
1335 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001336 * @param[in] ctx parser context.
1337 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001338 * @param[in,out] patterns Restrictions to add to.
1339 *
1340 * @return LY_ERR values.
1341 */
1342static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001343lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001344{
1345 char *buf;
1346 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001347 struct lysp_restr *restr;
1348
1349 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001350 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001351 arg_len = strlen(stmt->arg);
1352
1353 /* add special meaning first byte */
1354 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001355 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001356 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001357 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001358 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001359 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001360 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001361
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001362 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1363 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001364 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001365 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001366 break;
1367 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001368 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001369 break;
1370 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001371 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001372 break;
1373 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001374 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001375 break;
1376 case LY_STMT_MODIFIER:
1377 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001378 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001379 break;
1380 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001381 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001382 break;
1383 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001384 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001385 return LY_EVALID;
1386 }
1387 }
1388 return LY_SUCCESS;
1389}
1390
1391/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001392 * @brief Parse the deviate statement. Substatement of deviation statement.
1393 *
1394 * @param[in] ctx parser context.
1395 * @param[in] stmt Source statement data from the parsed extension instance.
1396 * @param[in,out] devs Array of deviates to add to.
1397 * @param[in,out] exts Extension instances to add to.
1398 * @return LY_ERR values.
1399 */
1400static LY_ERR
1401lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1402{
1403 (void)stmt;
1404 (void)devs;
1405 (void)exts;
1406
1407 /* TODO */
1408 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1409 return LY_EINVAL;
1410}
1411
1412/**
1413 * @brief Parse the deviation statement.
1414 *
1415 * @param[in] ctx parser context.
1416 * @param[in] stmt Source statement data from the parsed extension instance.
1417 * @param[in,out] deviations Array of deviations to add to.
1418 * @return LY_ERR values.
1419 */
1420static LY_ERR
1421lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1422{
1423 struct lysp_deviation *dev;
1424
1425 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1426
1427 /* store nodeid */
1428 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1429 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1430
1431 /* parse substatements */
1432 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1433 switch (child->kw) {
1434 case LY_STMT_DESCRIPTION:
1435 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1436 break;
1437 case LY_STMT_DEVIATE:
1438 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1439 break;
1440 case LY_STMT_REFERENCE:
1441 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1442 break;
1443 case LY_STMT_EXTENSION_INSTANCE:
1444 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1445 break;
1446 default:
1447 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1448 return LY_EVALID;
1449 }
1450 }
1451
1452 return LY_SUCCESS;
1453}
1454
1455/**
1456 * @brief Parse the yang-version statement.
1457 *
1458 * @param[in] ctx parser context.
1459 * @param[in] stmt Source statement data from the parsed extension instance.
1460 * @param[out] version Version to write to.
1461 * @param[in,out] exts Extension instances to add to.
1462 * @return LY_ERR values.
1463 */
1464static LY_ERR
1465lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1466{
1467 if (*version) {
1468 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1469 return LY_EVALID;
1470 }
1471
1472 /* store flag */
1473 if (!strcmp(stmt->arg, "1")) {
1474 *version = LYS_VERSION_1_0;
1475 } else if (!strcmp(stmt->arg, "1.1")) {
1476 *version = LYS_VERSION_1_1;
1477 } else {
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001478 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, (int)strlen(stmt->arg), stmt->arg, "yang-version");
Michal Vasko193dacd2022-10-13 08:43:05 +02001479 return LY_EVALID;
1480 }
1481
1482 /* parse substatements */
1483 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1484 switch (child->kw) {
1485 case LY_STMT_EXTENSION_INSTANCE:
1486 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1487 break;
1488 default:
1489 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1490 return LY_EVALID;
1491 }
1492 }
1493
1494 return LY_SUCCESS;
1495}
1496
1497/**
1498 * @brief Parse the module statement.
1499 *
1500 * @param[in] ctx parser context.
1501 * @param[in] stmt Source statement data from the parsed extension instance.
1502 * @param[in,out] mod Module to fill.
1503 * @return LY_ERR values.
1504 */
1505static LY_ERR
1506lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1507{
1508 (void)stmt;
1509 (void)mod;
1510
1511 /* TODO */
1512 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1513 return LY_EINVAL;
1514}
1515
1516/**
1517 * @brief Parse the submodule statement.
1518 *
1519 * @param[in] ctx parser context.
1520 * @param[in] stmt Source statement data from the parsed extension instance.
1521 * @param[in,out] submod Module to fill.
1522 * @return LY_ERR values.
1523 */
1524static LY_ERR
1525lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1526{
1527 (void)stmt;
1528 (void)submod;
1529
1530 /* TODO */
1531 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1532 return LY_EINVAL;
1533}
1534
1535/**
1536 * @brief Parse the yin-element statement. Substatement of argument statement.
1537 *
1538 * @param[in] ctx parser context.
1539 * @param[in] stmt Source statement data from the parsed extension instance.
1540 * @param[in,out] flags Flags to write to.
1541 * @param[in,out] exts Extension instances to add to.
1542 * @return LY_ERR values.
1543 */
1544static LY_ERR
1545lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1546{
1547 if (*flags & LYS_YINELEM_MASK) {
1548 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1549 return LY_EVALID;
1550 }
1551
1552 /* store flag */
1553 if (!strcmp(stmt->arg, "true")) {
1554 *flags |= LYS_YINELEM_TRUE;
1555 } else if (!strcmp(stmt->arg, "false")) {
1556 *flags |= LYS_YINELEM_FALSE;
1557 } else {
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001558 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, (int)strlen(stmt->arg), stmt->arg, "yin-element");
Michal Vasko193dacd2022-10-13 08:43:05 +02001559 return LY_EVALID;
1560 }
1561
1562 /* parse substatements */
1563 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1564 switch (child->kw) {
1565 case LY_STMT_EXTENSION_INSTANCE:
1566 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1567 break;
1568 default:
1569 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1570 return LY_EVALID;
1571 }
1572 }
1573
1574 return LY_SUCCESS;
1575}
1576
1577/**
1578 * @brief Parse the argument statement. Substatement of extension statement.
1579 *
1580 * @param[in] ctx parser context.
1581 * @param[in] stmt Source statement data from the parsed extension instance.
1582 * @param[in,out] ex Extension to fill.
1583 * @return LY_ERR values.
1584 */
1585static LY_ERR
1586lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1587{
1588 if (ex->argname) {
1589 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1590 return LY_EVALID;
1591 }
1592
1593 /* store argument name */
1594 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1595 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1596
1597 /* parse substatements */
1598 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1599 switch (child->kw) {
1600 case LY_STMT_YIN_ELEMENT:
1601 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1602 break;
1603 case LY_STMT_EXTENSION_INSTANCE:
1604 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1605 break;
1606 default:
1607 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1608 return LY_EVALID;
1609 }
1610 }
1611
1612 return LY_SUCCESS;
1613}
1614
1615/**
1616 * @brief Parse the extension statement.
1617 *
1618 * @param[in] ctx parser context.
1619 * @param[in] stmt Source statement data from the parsed extension instance.
1620 * @param[in,out] extensions Array of extensions to add to.
1621 * @return LY_ERR values.
1622 */
1623static LY_ERR
1624lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1625{
1626 struct lysp_ext *ex;
1627
1628 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1629
1630 /* store name */
1631 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1632 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1633
1634 /* parse substatements */
1635 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1636 switch (child->kw) {
1637 case LY_STMT_DESCRIPTION:
1638 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1639 break;
1640 case LY_STMT_REFERENCE:
1641 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1642 break;
1643 case LY_STMT_STATUS:
1644 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1645 break;
1646 case LY_STMT_ARGUMENT:
1647 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1648 break;
1649 case LY_STMT_EXTENSION_INSTANCE:
1650 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1651 break;
1652 default:
1653 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1654 return LY_EVALID;
1655 }
1656 }
1657
1658 return LY_SUCCESS;
1659}
1660
1661/**
1662 * @brief Parse the feature statement.
1663 *
1664 * @param[in] ctx parser context.
1665 * @param[in] stmt Source statement data from the parsed extension instance.
1666 * @param[in,out] features Array of features to add to.
1667 * @return LY_ERR values.
1668 */
1669static LY_ERR
1670lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1671{
1672 struct lysp_feature *feat;
1673
1674 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1675
1676 /* store name */
1677 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1678 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1679
1680 /* parse substatements */
1681 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1682 switch (child->kw) {
1683 case LY_STMT_DESCRIPTION:
1684 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1685 break;
1686 case LY_STMT_IF_FEATURE:
1687 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1688 break;
1689 case LY_STMT_REFERENCE:
1690 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1691 break;
1692 case LY_STMT_STATUS:
1693 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1694 break;
1695 case LY_STMT_EXTENSION_INSTANCE:
1696 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1697 break;
1698 default:
1699 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1700 return LY_EVALID;
1701 }
1702 }
1703
1704 return LY_SUCCESS;
1705}
1706
1707/**
1708 * @brief Parse the identity statement.
1709 *
1710 * @param[in] ctx parser context.
1711 * @param[in] stmt Source statement data from the parsed extension instance.
1712 * @param[in,out] identities Array of identities to add to.
1713 * @return LY_ERR values.
1714 */
1715static LY_ERR
1716lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1717{
1718 struct lysp_ident *ident;
1719
1720 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1721
1722 /* store name */
1723 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1724 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1725
1726 /* parse substatements */
1727 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1728 switch (child->kw) {
1729 case LY_STMT_DESCRIPTION:
1730 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1731 break;
1732 case LY_STMT_IF_FEATURE:
1733 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1734 break;
1735 case LY_STMT_REFERENCE:
1736 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1737 break;
1738 case LY_STMT_STATUS:
1739 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1740 break;
1741 case LY_STMT_BASE:
1742 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1743 break;
1744 case LY_STMT_EXTENSION_INSTANCE:
1745 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1746 break;
1747 default:
1748 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1749 return LY_EVALID;
1750 }
1751 }
1752
1753 return LY_SUCCESS;
1754}
1755
1756/**
1757 * @brief Parse the import statement.
1758 *
1759 * @param[in] ctx parser context.
1760 * @param[in] stmt Source statement data from the parsed extension instance.
1761 * @param[in,out] imports Array of imports to add to.
1762 * @return LY_ERR values.
1763 */
1764static LY_ERR
1765lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1766{
1767 struct lysp_import *imp;
1768 const char *str = NULL;
1769
1770 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1771
1772 /* store name */
1773 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1774 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1775
1776 /* parse substatements */
1777 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1778 switch (child->kw) {
1779 case LY_STMT_PREFIX:
1780 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1781 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1782 break;
1783 case LY_STMT_DESCRIPTION:
1784 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1785 break;
1786 case LY_STMT_REFERENCE:
1787 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1788 break;
1789 case LY_STMT_REVISION_DATE:
1790 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1791 strcpy(imp->rev, str);
1792 lydict_remove(PARSER_CTX(ctx), str);
1793 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1794 break;
1795 case LY_STMT_EXTENSION_INSTANCE:
1796 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1797 break;
1798 default:
1799 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1800 return LY_EVALID;
1801 }
1802 }
1803
1804 return LY_SUCCESS;
1805}
1806
1807/**
1808 * @brief Parse the include statement.
1809 *
1810 * @param[in] ctx parser context.
1811 * @param[in] stmt Source statement data from the parsed extension instance.
1812 * @param[in,out] includes Array of identities to add to.
1813 * @return LY_ERR values.
1814 */
1815static LY_ERR
1816lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1817{
1818 struct lysp_include *inc;
1819 const char *str = NULL;
1820
1821 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1822
1823 /* store name */
1824 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1825 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1826
1827 /* parse substatements */
1828 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1829 switch (child->kw) {
1830 case LY_STMT_DESCRIPTION:
1831 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1832 break;
1833 case LY_STMT_REFERENCE:
1834 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1835 break;
1836 case LY_STMT_REVISION_DATE:
1837 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1838 strcpy(inc->rev, str);
1839 lydict_remove(PARSER_CTX(ctx), str);
1840 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1841 break;
1842 case LY_STMT_EXTENSION_INSTANCE:
1843 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1844 break;
1845 default:
1846 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1847 return LY_EVALID;
1848 }
1849 }
1850
1851 return LY_SUCCESS;
1852}
1853
1854/**
1855 * @brief Parse the revision statement.
1856 *
1857 * @param[in] ctx parser context.
1858 * @param[in] stmt Source statement data from the parsed extension instance.
1859 * @param[in,out] includes Array of identities to add to.
1860 * @return LY_ERR values.
1861 */
1862static LY_ERR
1863lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1864{
1865 struct lysp_revision *rev;
1866
1867 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1868
1869 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001870 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001871 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001872
1873 /* parse substatements */
1874 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1875 switch (child->kw) {
1876 case LY_STMT_DESCRIPTION:
1877 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1878 break;
1879 case LY_STMT_REFERENCE:
1880 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1881 break;
1882 case LY_STMT_EXTENSION_INSTANCE:
1883 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1884 break;
1885 default:
1886 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1887 return LY_EVALID;
1888 }
1889 }
1890
1891 return LY_SUCCESS;
1892}
1893
1894/**
Radek Krejci335332a2019-09-05 13:03:35 +02001895 * @brief Parse the type statement.
1896 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001897 * @param[in] ctx parser context.
1898 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001899 * @param[in,out] type Type to wrote to.
1900 *
1901 * @return LY_ERR values.
1902 */
1903static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001904lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001905{
1906 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001907 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001908 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001909
1910 if (type->name) {
1911 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1912 return LY_EVALID;
1913 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001914
1915 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001916 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001917 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001918
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001919 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1920 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001921 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001922 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001923 type->flags |= LYS_SET_BASE;
1924 break;
1925 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001926 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001927 type->flags |= LYS_SET_BIT;
1928 break;
1929 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001930 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001931 type->flags |= LYS_SET_ENUM;
1932 break;
1933 case LY_STMT_FRACTION_DIGITS:
1934 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1935 type->flags |= LYS_SET_FRDIGITS;
1936 break;
1937 case LY_STMT_LENGTH:
1938 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001939 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001940 return LY_EVALID;
1941 }
1942 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001943 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001944
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001945 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001946 type->flags |= LYS_SET_LENGTH;
1947 break;
1948 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001949 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001950 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001951 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001952 lydict_remove(PARSER_CTX(ctx), str_path);
1953 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001954 type->flags |= LYS_SET_PATH;
1955 break;
1956 case LY_STMT_PATTERN:
1957 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1958 type->flags |= LYS_SET_PATTERN;
1959 break;
1960 case LY_STMT_RANGE:
1961 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001962 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001963 return LY_EVALID;
1964 }
1965 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001966 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001967
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001968 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001969 type->flags |= LYS_SET_RANGE;
1970 break;
1971 case LY_STMT_REQUIRE_INSTANCE:
1972 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001973 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001974 break;
1975 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001976 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001977 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1978 type->flags |= LYS_SET_TYPE;
1979 break;
1980 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001981 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001982 break;
1983 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001984 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001985 return LY_EVALID;
1986 }
1987 }
1988 return LY_SUCCESS;
1989}
1990
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001991/**
1992 * @brief Parse the leaf statement.
1993 *
1994 * @param[in] ctx parser context.
1995 * @param[in] stmt Source statement data from the parsed extension instance.
1996 * @param[in] parent Parent node to connect to (not into).
1997 * @param[in,out] siblings Siblings to add to.
1998 *
1999 * @return LY_ERR values.
2000 */
2001static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002002lysp_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 +01002003{
2004 struct lysp_node_leaf *leaf;
2005
2006 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2007
2008 /* create new leaf structure */
2009 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
2010 leaf->nodetype = LYS_LEAF;
2011 leaf->parent = parent;
2012
2013 /* get name */
2014 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
2015
2016 /* parse substatements */
2017 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2018 switch (child->kw) {
2019 case LY_STMT_CONFIG:
2020 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
2021 break;
2022 case LY_STMT_DEFAULT:
2023 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 +01002024 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002025 break;
2026 case LY_STMT_DESCRIPTION:
2027 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
2028 break;
2029 case LY_STMT_IF_FEATURE:
2030 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
2031 break;
2032 case LY_STMT_MANDATORY:
2033 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
2034 break;
2035 case LY_STMT_MUST:
2036 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
2037 break;
2038 case LY_STMT_REFERENCE:
2039 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
2040 break;
2041 case LY_STMT_STATUS:
2042 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
2043 break;
2044 case LY_STMT_TYPE:
2045 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
2046 break;
2047 case LY_STMT_UNITS:
2048 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
2049 break;
2050 case LY_STMT_WHEN:
2051 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
2052 break;
2053 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002054 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002055 break;
2056 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002057 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002058 return LY_EVALID;
2059 }
2060 }
2061
2062 /* mandatory substatements */
2063 if (!leaf->type.name) {
2064 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
2065 return LY_EVALID;
2066 }
2067
2068 return LY_SUCCESS;
2069}
2070
2071/**
2072 * @brief Parse the max-elements statement.
2073 *
2074 * @param[in] ctx parser context.
2075 * @param[in] stmt Source statement data from the parsed extension instance.
2076 * @param[in,out] max Value to write to.
2077 * @param[in,out] flags Flags to write to.
2078 * @param[in,out] exts Extension instances to add to.
2079 *
2080 * @return LY_ERR values.
2081 */
2082static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002083lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
2084 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002085{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002086 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002087 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002088 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002089
2090 if (*flags & LYS_SET_MAX) {
2091 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
2092 return LY_EVALID;
2093 }
2094 *flags |= LYS_SET_MAX;
2095
2096 /* get value */
2097 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2098 arg_len = strlen(stmt->arg);
2099
2100 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
2101 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
2102 return LY_EVALID;
2103 }
2104
2105 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
2106 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002107 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002108 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002109 if (ptr - stmt->arg != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002110 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
2111 return LY_EVALID;
2112 }
2113 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2114 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
2115 return LY_EVALID;
2116 }
2117
2118 *max = num;
2119 } else {
2120 /* unbounded */
2121 *max = 0;
2122 }
2123
2124 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2125 switch (child->kw) {
2126 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002127 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002128 break;
2129 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002130 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002131 return LY_EVALID;
2132 }
2133 }
2134
2135 return LY_SUCCESS;
2136}
2137
2138/**
2139 * @brief Parse the min-elements statement.
2140 *
2141 * @param[in] ctx parser context.
2142 * @param[in] stmt Source statement data from the parsed extension instance.
2143 * @param[in,out] min Value to write to.
2144 * @param[in,out] flags Flags to write to.
2145 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002146 * @return LY_ERR values.
2147 */
2148static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002149lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
2150 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002151{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002152 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002153 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002154 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002155
2156 if (*flags & LYS_SET_MIN) {
2157 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
2158 return LY_EVALID;
2159 }
2160 *flags |= LYS_SET_MIN;
2161
2162 /* get value */
2163 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2164 arg_len = strlen(stmt->arg);
2165
2166 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
2167 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2168 return LY_EVALID;
2169 }
2170
2171 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002172 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002173 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002174 if (ptr - stmt->arg != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002175 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2176 return LY_EVALID;
2177 }
2178 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2179 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
2180 return LY_EVALID;
2181 }
2182 *min = num;
2183
2184 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2185 switch (child->kw) {
2186 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002187 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002188 break;
2189 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002190 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002191 return LY_EVALID;
2192 }
2193 }
2194
2195 return LY_SUCCESS;
2196}
2197
2198/**
2199 * @brief Parse the ordered-by statement.
2200 *
2201 * @param[in] ctx parser context.
2202 * @param[in] stmt Source statement data from the parsed extension instance.
2203 * @param[in,out] flags Flags to write to.
2204 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002205 * @return LY_ERR values.
2206 */
2207static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002208lysp_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 +01002209{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002210 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002211
2212 if (*flags & LYS_ORDBY_MASK) {
2213 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2214 return LY_EVALID;
2215 }
2216
2217 /* get value */
2218 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2219 arg_len = strlen(stmt->arg);
2220 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2221 *flags |= LYS_MAND_TRUE;
2222 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2223 *flags |= LYS_MAND_FALSE;
2224 } else {
2225 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2226 return LY_EVALID;
2227 }
2228
2229 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2230 switch (child->kw) {
2231 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002232 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002233 break;
2234 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002235 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002236 return LY_EVALID;
2237 }
2238 }
2239
2240 return LY_SUCCESS;
2241}
2242
2243/**
2244 * @brief Parse the leaf-list statement.
2245 *
2246 * @param[in] ctx parser context.
2247 * @param[in] stmt Source statement data from the parsed extension instance.
2248 * @param[in] parent Parent node to connect to (not into).
2249 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002250 * @return LY_ERR values.
2251 */
2252static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002253lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002254 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002255{
2256 struct lysp_node_leaflist *llist;
2257
2258 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2259
2260 /* create new leaf-list structure */
2261 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2262 llist->nodetype = LYS_LEAFLIST;
2263 llist->parent = parent;
2264
2265 /* get name */
2266 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2267
2268 /* parse substatements */
2269 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2270 switch (child->kw) {
2271 case LY_STMT_CONFIG:
2272 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2273 break;
2274 case LY_STMT_DEFAULT:
2275 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2276 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2277 break;
2278 case LY_STMT_DESCRIPTION:
2279 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2280 break;
2281 case LY_STMT_IF_FEATURE:
2282 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2283 break;
2284 case LY_STMT_MAX_ELEMENTS:
2285 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2286 break;
2287 case LY_STMT_MIN_ELEMENTS:
2288 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2289 break;
2290 case LY_STMT_MUST:
2291 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2292 break;
2293 case LY_STMT_ORDERED_BY:
2294 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2295 break;
2296 case LY_STMT_REFERENCE:
2297 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2298 break;
2299 case LY_STMT_STATUS:
2300 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2301 break;
2302 case LY_STMT_TYPE:
2303 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2304 break;
2305 case LY_STMT_UNITS:
2306 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2307 break;
2308 case LY_STMT_WHEN:
2309 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2310 break;
2311 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002312 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002313 break;
2314 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002315 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002316 return LY_EVALID;
2317 }
2318 }
2319
2320 /* mandatory substatements */
2321 if (!llist->type.name) {
2322 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2323 return LY_EVALID;
2324 }
2325
2326 return LY_SUCCESS;
2327}
2328
2329/**
2330 * @brief Parse the refine statement.
2331 *
2332 * @param[in] ctx parser context.
2333 * @param[in] stmt Source statement data from the parsed extension instance.
2334 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002335 * @return LY_ERR values.
2336 */
2337static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002338lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002339{
2340 struct lysp_refine *rf;
2341
2342 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2343
2344 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2345
2346 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2347
2348 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2349 switch (child->kw) {
2350 case LY_STMT_CONFIG:
2351 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2352 break;
2353 case LY_STMT_DEFAULT:
2354 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2355 break;
2356 case LY_STMT_DESCRIPTION:
2357 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2358 break;
2359 case LY_STMT_IF_FEATURE:
2360 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2361 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2362 break;
2363 case LY_STMT_MAX_ELEMENTS:
2364 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2365 break;
2366 case LY_STMT_MIN_ELEMENTS:
2367 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2368 break;
2369 case LY_STMT_MUST:
2370 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2371 break;
2372 case LY_STMT_MANDATORY:
2373 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2374 break;
2375 case LY_STMT_REFERENCE:
2376 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2377 break;
2378 case LY_STMT_PRESENCE:
2379 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2380 break;
2381 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002382 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002383 break;
2384 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002385 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002386 return LY_EVALID;
2387 }
2388 }
2389
2390 return LY_SUCCESS;
2391}
2392
2393/**
2394 * @brief Parse the typedef statement.
2395 *
2396 * @param[in] ctx parser context.
2397 * @param[in] stmt Source statement data from the parsed extension instance.
2398 * @param[in] parent Parent node to connect to (not into).
2399 * @param[in,out] typedefs Typedefs to add to.
2400 *
2401 * @return LY_ERR values.
2402 */
2403static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002404lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002405 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002406{
2407 struct lysp_tpdf *tpdf;
2408
2409 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2410
2411 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2412
2413 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2414
2415 /* parse substatements */
2416 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2417 switch (child->kw) {
2418 case LY_STMT_DEFAULT:
2419 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 +01002420 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002421 break;
2422 case LY_STMT_DESCRIPTION:
2423 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2424 break;
2425 case LY_STMT_REFERENCE:
2426 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2427 break;
2428 case LY_STMT_STATUS:
2429 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2430 break;
2431 case LY_STMT_TYPE:
2432 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2433 break;
2434 case LY_STMT_UNITS:
2435 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2436 break;
2437 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002438 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002439 break;
2440 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002441 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002442 return LY_EVALID;
2443 }
2444 }
2445
2446 /* mandatory substatements */
2447 if (!tpdf->type.name) {
2448 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2449 return LY_EVALID;
2450 }
2451
2452 /* store data for collision check */
2453 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2454 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2455 }
2456
2457 return LY_SUCCESS;
2458}
2459
2460/**
2461 * @brief Parse the input or output statement.
2462 *
2463 * @param[in] ctx parser context.
2464 * @param[in] stmt Source statement data from the parsed extension instance.
2465 * @param[in] parent Parent node to connect to (not into).
2466 * @param[in,out] inout_p Input/output pointer to write to.
2467 *
2468 * @return LY_ERR values.
2469 */
2470static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002471lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002472 struct lysp_node_action_inout *inout_p)
2473{
2474 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002475 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002476 return LY_EVALID;
2477 }
2478
2479 /* initiate structure */
2480 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2481 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2482 inout_p->parent = parent;
2483
2484 /* parse substatements */
2485 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2486 switch (child->kw) {
2487 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002488 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002489 /* fall through */
2490 case LY_STMT_ANYXML:
2491 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2492 break;
2493 case LY_STMT_CHOICE:
2494 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2495 break;
2496 case LY_STMT_CONTAINER:
2497 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2498 break;
2499 case LY_STMT_LEAF:
2500 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2501 break;
2502 case LY_STMT_LEAF_LIST:
2503 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2504 break;
2505 case LY_STMT_LIST:
2506 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2507 break;
2508 case LY_STMT_USES:
2509 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2510 break;
2511 case LY_STMT_TYPEDEF:
2512 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2513 break;
2514 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002515 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002516 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2517 break;
2518 case LY_STMT_GROUPING:
2519 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2520 break;
2521 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002522 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002523 break;
2524 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002525 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002526 return LY_EVALID;
2527 }
2528 }
2529
2530 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002531 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002532 return LY_EVALID;
2533 }
2534
2535 return LY_SUCCESS;
2536}
2537
2538/**
2539 * @brief Parse the action statement.
2540 *
2541 * @param[in] ctx parser context.
2542 * @param[in] stmt Source statement data from the parsed extension instance.
2543 * @param[in] parent Parent node to connect to (not into).
2544 * @param[in,out] actions Actions to add to.
2545 *
2546 * @return LY_ERR values.
2547 */
2548static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002549lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002550 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002551{
2552 struct lysp_node_action *act;
2553
2554 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2555
2556 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2557
2558 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2559 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2560 act->parent = parent;
2561
2562 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2563 switch (child->kw) {
2564 case LY_STMT_DESCRIPTION:
2565 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2566 break;
2567 case LY_STMT_IF_FEATURE:
2568 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2569 break;
2570 case LY_STMT_REFERENCE:
2571 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2572 break;
2573 case LY_STMT_STATUS:
2574 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2575 break;
2576
2577 case LY_STMT_INPUT:
2578 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2579 break;
2580 case LY_STMT_OUTPUT:
2581 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2582 break;
2583
2584 case LY_STMT_TYPEDEF:
2585 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2586 break;
2587 case LY_STMT_GROUPING:
2588 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2589 break;
2590 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002591 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 +01002592 break;
2593 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002594 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002595 return LY_EVALID;
2596 }
2597 }
2598
2599 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2600 if (!act->input.nodetype) {
2601 act->input.nodetype = LYS_INPUT;
2602 act->input.parent = &act->node;
2603 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2604 }
2605 if (!act->output.nodetype) {
2606 act->output.nodetype = LYS_OUTPUT;
2607 act->output.parent = &act->node;
2608 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2609 }
2610
2611 return LY_SUCCESS;
2612}
2613
2614/**
2615 * @brief Parse the notification statement.
2616 *
2617 * @param[in] ctx parser context.
2618 * @param[in] stmt Source statement data from the parsed extension instance.
2619 * @param[in] parent Parent node to connect to (not into).
2620 * @param[in,out] notifs Notifications to add to.
2621 *
2622 * @return LY_ERR values.
2623 */
2624static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002625lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002626 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002627{
2628 struct lysp_node_notif *notif;
2629
2630 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2631
2632 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2633
2634 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2635 notif->nodetype = LYS_NOTIF;
2636 notif->parent = parent;
2637
2638 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2639 switch (child->kw) {
2640 case LY_STMT_DESCRIPTION:
2641 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2642 break;
2643 case LY_STMT_IF_FEATURE:
2644 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2645 break;
2646 case LY_STMT_REFERENCE:
2647 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2648 break;
2649 case LY_STMT_STATUS:
2650 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2651 break;
2652
2653 case LY_STMT_ANYDATA:
2654 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2655 /* fall through */
2656 case LY_STMT_ANYXML:
2657 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2658 break;
2659 case LY_STMT_CHOICE:
2660 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2661 break;
2662 case LY_STMT_CONTAINER:
2663 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2664 break;
2665 case LY_STMT_LEAF:
2666 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2667 break;
2668 case LY_STMT_LEAF_LIST:
2669 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2670 break;
2671 case LY_STMT_LIST:
2672 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2673 break;
2674 case LY_STMT_USES:
2675 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2676 break;
2677
2678 case LY_STMT_MUST:
2679 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2680 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2681 break;
2682 case LY_STMT_TYPEDEF:
2683 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2684 break;
2685 case LY_STMT_GROUPING:
2686 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2687 break;
2688 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002689 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002690 break;
2691 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002692 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002693 return LY_EVALID;
2694 }
2695 }
2696
2697 return LY_SUCCESS;
2698}
2699
2700/**
2701 * @brief Parse the grouping statement.
2702 *
2703 * @param[in] ctx parser context.
2704 * @param[in] stmt Source statement data from the parsed extension instance.
2705 * @param[in] parent Parent node to connect to (not into).
2706 * @param[in,out] groupings Groupings to add to.
2707 *
2708 * @return LY_ERR values.
2709 */
2710static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002711lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002712 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002713{
2714 struct lysp_node_grp *grp;
2715
2716 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2717
2718 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2719
2720 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2721 grp->nodetype = LYS_GROUPING;
2722 grp->parent = parent;
2723
2724 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2725 switch (child->kw) {
2726 case LY_STMT_DESCRIPTION:
2727 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2728 break;
2729 case LY_STMT_REFERENCE:
2730 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2731 break;
2732 case LY_STMT_STATUS:
2733 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2734 break;
2735
2736 case LY_STMT_ANYDATA:
2737 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2738 /* fall through */
2739 case LY_STMT_ANYXML:
2740 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2741 break;
2742 case LY_STMT_CHOICE:
2743 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2744 break;
2745 case LY_STMT_CONTAINER:
2746 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2747 break;
2748 case LY_STMT_LEAF:
2749 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2750 break;
2751 case LY_STMT_LEAF_LIST:
2752 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2753 break;
2754 case LY_STMT_LIST:
2755 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2756 break;
2757 case LY_STMT_USES:
2758 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2759 break;
2760
2761 case LY_STMT_TYPEDEF:
2762 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2763 break;
2764 case LY_STMT_ACTION:
2765 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2766 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2767 break;
2768 case LY_STMT_GROUPING:
2769 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2770 break;
2771 case LY_STMT_NOTIFICATION:
2772 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2773 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2774 break;
2775 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002776 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002777 break;
2778 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002779 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002780 return LY_EVALID;
2781 }
2782 }
2783
2784 return LY_SUCCESS;
2785}
2786
2787/**
2788 * @brief Parse the augment statement.
2789 *
2790 * @param[in] ctx parser context.
2791 * @param[in] stmt Source statement data from the parsed extension instance.
2792 * @param[in] parent Parent node to connect to (not into).
2793 * @param[in,out] augments Augments to add to.
2794 *
2795 * @return LY_ERR values.
2796 */
2797static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002798lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002799 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002800{
2801 struct lysp_node_augment *aug;
2802
2803 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2804
2805 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2806
2807 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2808 aug->nodetype = LYS_AUGMENT;
2809 aug->parent = parent;
2810
2811 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2812 switch (child->kw) {
2813 case LY_STMT_DESCRIPTION:
2814 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2815 break;
2816 case LY_STMT_IF_FEATURE:
2817 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2818 break;
2819 case LY_STMT_REFERENCE:
2820 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2821 break;
2822 case LY_STMT_STATUS:
2823 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2824 break;
2825 case LY_STMT_WHEN:
2826 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2827 break;
2828
2829 case LY_STMT_ANYDATA:
2830 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2831 /* fall through */
2832 case LY_STMT_ANYXML:
2833 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2834 break;
2835 case LY_STMT_CASE:
2836 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2837 break;
2838 case LY_STMT_CHOICE:
2839 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2840 break;
2841 case LY_STMT_CONTAINER:
2842 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2843 break;
2844 case LY_STMT_LEAF:
2845 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2846 break;
2847 case LY_STMT_LEAF_LIST:
2848 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2849 break;
2850 case LY_STMT_LIST:
2851 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2852 break;
2853 case LY_STMT_USES:
2854 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2855 break;
2856
2857 case LY_STMT_ACTION:
2858 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2859 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2860 break;
2861 case LY_STMT_NOTIFICATION:
2862 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2863 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2864 break;
2865 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002866 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002867 break;
2868 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002869 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002870 return LY_EVALID;
2871 }
2872 }
2873
2874 return LY_SUCCESS;
2875}
2876
2877/**
2878 * @brief Parse the uses statement.
2879 *
2880 * @param[in] ctx parser context.
2881 * @param[in] stmt Source statement data from the parsed extension instance.
2882 * @param[in] parent Parent node to connect to (not into).
2883 * @param[in,out] siblings Siblings to add to.
2884 *
2885 * @return LY_ERR values.
2886 */
2887static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002888lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002889 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002890{
2891 struct lysp_node_uses *uses;
2892
2893 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2894
2895 /* create uses structure */
2896 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2897
2898 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2899 uses->nodetype = LYS_USES;
2900 uses->parent = parent;
2901
2902 /* parse substatements */
2903 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2904 switch (child->kw) {
2905 case LY_STMT_DESCRIPTION:
2906 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2907 break;
2908 case LY_STMT_IF_FEATURE:
2909 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2910 break;
2911 case LY_STMT_REFERENCE:
2912 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2913 break;
2914 case LY_STMT_STATUS:
2915 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2916 break;
2917 case LY_STMT_WHEN:
2918 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2919 break;
2920
2921 case LY_STMT_REFINE:
2922 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2923 break;
2924 case LY_STMT_AUGMENT:
2925 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2926 break;
2927 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002928 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002929 break;
2930 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002931 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002932 return LY_EVALID;
2933 }
2934 }
2935
2936 return LY_SUCCESS;
2937}
2938
2939/**
2940 * @brief Parse the case statement.
2941 *
2942 * @param[in] ctx parser context.
2943 * @param[in] stmt Source statement data from the parsed extension instance.
2944 * @param[in] parent Parent node to connect to (not into).
2945 * @param[in,out] siblings Siblings to add to.
2946 *
2947 * @return LY_ERR values.
2948 */
2949static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002950lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002951 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002952{
2953 struct lysp_node_case *cas;
2954
2955 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2956
2957 /* create new case structure */
2958 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2959
2960 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2961 cas->nodetype = LYS_CASE;
2962 cas->parent = parent;
2963
2964 /* parse substatements */
2965 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2966 switch (child->kw) {
2967 case LY_STMT_DESCRIPTION:
2968 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2969 break;
2970 case LY_STMT_IF_FEATURE:
2971 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2972 break;
2973 case LY_STMT_REFERENCE:
2974 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2975 break;
2976 case LY_STMT_STATUS:
2977 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2978 break;
2979 case LY_STMT_WHEN:
2980 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2981 break;
2982
2983 case LY_STMT_ANYDATA:
2984 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2985 /* fall through */
2986 case LY_STMT_ANYXML:
2987 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2988 break;
2989 case LY_STMT_CHOICE:
2990 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2991 break;
2992 case LY_STMT_CONTAINER:
2993 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2994 break;
2995 case LY_STMT_LEAF:
2996 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2997 break;
2998 case LY_STMT_LEAF_LIST:
2999 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
3000 break;
3001 case LY_STMT_LIST:
3002 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
3003 break;
3004 case LY_STMT_USES:
3005 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
3006 break;
3007 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003008 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003009 break;
3010 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003011 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003012 return LY_EVALID;
3013 }
3014 }
3015 return LY_SUCCESS;
3016}
3017
3018/**
3019 * @brief Parse the choice statement.
3020 *
3021 * @param[in] ctx parser context.
3022 * @param[in] stmt Source statement data from the parsed extension instance.
3023 * @param[in] parent Parent node to connect to (not into).
3024 * @param[in,out] siblings Siblings to add to.
3025 *
3026 * @return LY_ERR values.
3027 */
3028static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003029lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003030 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003031{
3032 struct lysp_node_choice *choice;
3033
3034 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3035
3036 /* create new choice structure */
3037 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
3038
3039 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
3040 choice->nodetype = LYS_CHOICE;
3041 choice->parent = parent;
3042
3043 /* parse substatements */
3044 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3045 switch (child->kw) {
3046 case LY_STMT_CONFIG:
3047 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
3048 break;
3049 case LY_STMT_DESCRIPTION:
3050 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
3051 break;
3052 case LY_STMT_IF_FEATURE:
3053 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
3054 break;
3055 case LY_STMT_MANDATORY:
3056 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
3057 break;
3058 case LY_STMT_REFERENCE:
3059 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
3060 break;
3061 case LY_STMT_STATUS:
3062 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
3063 break;
3064 case LY_STMT_WHEN:
3065 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
3066 break;
3067 case LY_STMT_DEFAULT:
3068 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 +01003069 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003070 break;
3071 case LY_STMT_ANYDATA:
3072 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
3073 /* fall through */
3074 case LY_STMT_ANYXML:
3075 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
3076 break;
3077 case LY_STMT_CASE:
3078 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
3079 break;
3080 case LY_STMT_CHOICE:
3081 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
3082 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
3083 break;
3084 case LY_STMT_CONTAINER:
3085 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
3086 break;
3087 case LY_STMT_LEAF:
3088 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
3089 break;
3090 case LY_STMT_LEAF_LIST:
3091 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
3092 break;
3093 case LY_STMT_LIST:
3094 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
3095 break;
3096 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003097 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003098 break;
3099 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003100 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003101 return LY_EVALID;
3102 }
3103 }
3104 return LY_SUCCESS;
3105}
3106
3107/**
3108 * @brief Parse the container statement.
3109 *
3110 * @param[in] ctx parser context.
3111 * @param[in] stmt Source statement data from the parsed extension instance.
3112 * @param[in] parent Parent node to connect to (not into).
3113 * @param[in,out] siblings Siblings to add to.
3114 *
3115 * @return LY_ERR values.
3116 */
3117static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003118lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003119 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003120{
3121 struct lysp_node_container *cont;
3122
3123 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3124
3125 /* create new container structure */
3126 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
3127
3128 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
3129 cont->nodetype = LYS_CONTAINER;
3130 cont->parent = parent;
3131
3132 /* parse substatements */
3133 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3134 switch (child->kw) {
3135 case LY_STMT_CONFIG:
3136 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
3137 break;
3138 case LY_STMT_DESCRIPTION:
3139 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
3140 break;
3141 case LY_STMT_IF_FEATURE:
3142 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
3143 break;
3144 case LY_STMT_REFERENCE:
3145 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
3146 break;
3147 case LY_STMT_STATUS:
3148 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
3149 break;
3150 case LY_STMT_WHEN:
3151 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
3152 break;
3153 case LY_STMT_PRESENCE:
3154 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
3155 break;
3156 case LY_STMT_ANYDATA:
3157 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
3158 /* fall through */
3159 case LY_STMT_ANYXML:
3160 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
3161 break;
3162 case LY_STMT_CHOICE:
3163 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
3164 break;
3165 case LY_STMT_CONTAINER:
3166 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
3167 break;
3168 case LY_STMT_LEAF:
3169 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
3170 break;
3171 case LY_STMT_LEAF_LIST:
3172 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
3173 break;
3174 case LY_STMT_LIST:
3175 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
3176 break;
3177 case LY_STMT_USES:
3178 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
3179 break;
3180
3181 case LY_STMT_TYPEDEF:
3182 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
3183 break;
3184 case LY_STMT_MUST:
3185 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
3186 break;
3187 case LY_STMT_ACTION:
3188 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
3189 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
3190 break;
3191 case LY_STMT_GROUPING:
3192 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3193 break;
3194 case LY_STMT_NOTIFICATION:
3195 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3196 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3197 break;
3198 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003199 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003200 break;
3201 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003202 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003203 return LY_EVALID;
3204 }
3205 }
3206
3207 return LY_SUCCESS;
3208}
3209
3210/**
3211 * @brief Parse the list statement.
3212 *
3213 * @param[in] ctx parser context.
3214 * @param[in] stmt Source statement data from the parsed extension instance.
3215 * @param[in] parent Parent node to connect to (not into).
3216 * @param[in,out] siblings Siblings to add to.
3217 *
3218 * @return LY_ERR values.
3219 */
3220static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003221lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003222 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003223{
3224 struct lysp_node_list *list;
3225
3226 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3227
3228 /* create new list structure */
3229 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3230
3231 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3232 list->nodetype = LYS_LIST;
3233 list->parent = parent;
3234
3235 /* parse substatements */
3236 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3237 switch (child->kw) {
3238 case LY_STMT_CONFIG:
3239 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3240 break;
3241 case LY_STMT_DESCRIPTION:
3242 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3243 break;
3244 case LY_STMT_IF_FEATURE:
3245 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3246 break;
3247 case LY_STMT_REFERENCE:
3248 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3249 break;
3250 case LY_STMT_STATUS:
3251 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3252 break;
3253 case LY_STMT_WHEN:
3254 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3255 break;
3256 case LY_STMT_KEY:
3257 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3258 break;
3259 case LY_STMT_MAX_ELEMENTS:
3260 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3261 break;
3262 case LY_STMT_MIN_ELEMENTS:
3263 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3264 break;
3265 case LY_STMT_ORDERED_BY:
3266 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3267 break;
3268 case LY_STMT_UNIQUE:
3269 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3270 break;
3271
3272 case LY_STMT_ANYDATA:
3273 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3274 /* fall through */
3275 case LY_STMT_ANYXML:
3276 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3277 break;
3278 case LY_STMT_CHOICE:
3279 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3280 break;
3281 case LY_STMT_CONTAINER:
3282 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3283 break;
3284 case LY_STMT_LEAF:
3285 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3286 break;
3287 case LY_STMT_LEAF_LIST:
3288 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3289 break;
3290 case LY_STMT_LIST:
3291 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3292 break;
3293 case LY_STMT_USES:
3294 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3295 break;
3296
3297 case LY_STMT_TYPEDEF:
3298 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3299 break;
3300 case LY_STMT_MUST:
3301 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3302 break;
3303 case LY_STMT_ACTION:
3304 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3305 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3306 break;
3307 case LY_STMT_GROUPING:
3308 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3309 break;
3310 case LY_STMT_NOTIFICATION:
3311 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3312 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3313 break;
3314 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003315 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003316 break;
3317 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003318 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003319 return LY_EVALID;
3320 }
3321 }
3322
3323 return LY_SUCCESS;
3324}
3325
Michal Vasko193dacd2022-10-13 08:43:05 +02003326/**
3327 * @brief Parse generic statement structure into a specific parsed-schema structure.
3328 *
3329 * @param[in] pctx Parse context of the @p stmt being processed.
3330 * @param[in] stmt Generic statement structure to process.
3331 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3332 * @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.
3333 * @return LY_ERR value.
3334 */
3335static LY_ERR
3336lysp_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 +02003337{
Radek Krejciad5963b2019-09-06 16:03:05 +02003338 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003339 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003340
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003341 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003342 case LY_STMT_NOTIFICATION:
3343 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3344 break;
3345 case LY_STMT_INPUT:
3346 case LY_STMT_OUTPUT: {
3347 struct lysp_node_action_inout *inout;
3348
3349 *result = inout = calloc(1, sizeof *inout);
3350 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3351 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3352 break;
3353 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003354 case LY_STMT_ACTION:
3355 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003356 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003357 break;
3358 case LY_STMT_ANYDATA:
3359 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003360 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003361 break;
3362 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003363 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003364 break;
3365 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003366 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003367 break;
3368 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003369 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003370 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003371 case LY_STMT_CONTAINER:
3372 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003373 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003374 case LY_STMT_GROUPING:
3375 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3376 break;
3377 case LY_STMT_LEAF:
3378 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3379 break;
3380 case LY_STMT_LEAF_LIST:
3381 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3382 break;
3383 case LY_STMT_LIST:
3384 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3385 break;
3386 case LY_STMT_USES:
3387 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3388 break;
3389 case LY_STMT_BASE:
3390 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3391 break;
3392 case LY_STMT_ARGUMENT:
3393 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003394 case LY_STMT_CONTACT:
3395 case LY_STMT_DESCRIPTION:
3396 case LY_STMT_ERROR_APP_TAG:
3397 case LY_STMT_ERROR_MESSAGE:
3398 case LY_STMT_KEY:
3399 case LY_STMT_NAMESPACE:
3400 case LY_STMT_ORGANIZATION:
3401 case LY_STMT_PRESENCE:
3402 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003403 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003404 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003405 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003406 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003407 case LY_STMT_BIT:
3408 case LY_STMT_ENUM:
3409 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3410 break;
3411 case LY_STMT_CONFIG:
3412 assert(*result);
3413 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003414 break;
3415 case LY_STMT_DEFAULT:
3416 case LY_STMT_IF_FEATURE:
3417 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003418 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3419 break;
3420 case LY_STMT_DEVIATE:
3421 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3422 break;
3423 case LY_STMT_DEVIATION:
3424 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3425 break;
3426 case LY_STMT_EXTENSION:
3427 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003428 break;
3429 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003430 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3431 break;
3432 case LY_STMT_FEATURE:
3433 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003434 break;
3435 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003436 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003437 break;
3438 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003439 case LY_STMT_RANGE: {
3440 struct lysp_restr *restr;
3441
3442 *result = restr = calloc(1, sizeof *restr);
3443 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3444
3445 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003446 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003447 }
3448 case LY_STMT_MUST:
3449 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3450 break;
3451 case LY_STMT_IDENTITY:
3452 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3453 break;
3454 case LY_STMT_IMPORT:
3455 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3456 break;
3457 case LY_STMT_INCLUDE:
3458 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003459 break;
3460 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003461 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003462 break;
3463 case LY_STMT_MAX_ELEMENTS:
3464 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003465 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003466 break;
3467 case LY_STMT_MIN_ELEMENTS:
3468 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003469 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003470 break;
3471 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003472 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003473 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003474 case LY_STMT_MODULE: {
3475 struct lysp_module *mod;
3476
3477 *result = mod = calloc(1, sizeof *mod);
3478 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3479 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003480 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003481 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003482 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003483 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003484 break;
3485 case LY_STMT_PATH: {
3486 const char *str_path = NULL;
3487
Michal Vasko193dacd2022-10-13 08:43:05 +02003488 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3489 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003490 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003491 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003492 break;
3493 }
3494 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003495 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003496 break;
3497 case LY_STMT_POSITION:
3498 case LY_STMT_VALUE:
3499 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003500 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003501 break;
3502 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003503 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003504 break;
3505 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003506 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003507 break;
3508 case LY_STMT_REQUIRE_INSTANCE:
3509 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003510 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3511 break;
3512 case LY_STMT_REVISION:
3513 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003514 break;
Michal Vasko69730152020-10-09 16:30:07 +02003515 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003516 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003517 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003518 case LY_STMT_SUBMODULE: {
3519 struct lysp_submodule *submod;
3520
3521 *result = submod = calloc(1, sizeof *submod);
3522 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3523 ret = lysp_stmt_submodule(pctx, stmt, submod);
3524 break;
3525 }
Radek Krejci335332a2019-09-05 13:03:35 +02003526 case LY_STMT_TYPE: {
3527 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003528
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003529 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003530 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3531 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003532 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003533 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003534 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003535 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003536 break;
3537 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003538 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3539 break;
3540 case LY_STMT_YANG_VERSION:
3541 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3542 break;
3543 case LY_STMT_YIN_ELEMENT:
3544 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003545 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003546 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003547 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003548 return LY_EINT;
3549 }
3550
Radek Krejciad5963b2019-09-06 16:03:05 +02003551 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003552}
Michal Vasko59892dd2022-05-13 11:02:30 +02003553
Michal Vasko193dacd2022-10-13 08:43:05 +02003554LY_ERR
3555lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003556{
Michal Vasko193dacd2022-10-13 08:43:05 +02003557 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003558
Michal Vasko193dacd2022-10-13 08:43:05 +02003559 if (!substmt->storage) {
3560 /* nothing to parse, ignored */
3561 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003562 }
3563
Michal Vasko193dacd2022-10-13 08:43:05 +02003564 switch (stmt->kw) {
3565 case LY_STMT_NOTIFICATION:
3566 case LY_STMT_INPUT:
3567 case LY_STMT_OUTPUT:
3568 case LY_STMT_ACTION:
3569 case LY_STMT_RPC:
3570 case LY_STMT_ANYDATA:
3571 case LY_STMT_ANYXML:
3572 case LY_STMT_AUGMENT:
3573 case LY_STMT_CASE:
3574 case LY_STMT_CHOICE:
3575 case LY_STMT_CONTAINER:
3576 case LY_STMT_GROUPING:
3577 case LY_STMT_LEAF:
3578 case LY_STMT_LEAF_LIST:
3579 case LY_STMT_LIST:
3580 case LY_STMT_USES: {
3581 struct lysp_node **pnodes_p, *pnode = NULL;
3582
3583 /* parse the node */
3584 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3585
3586 /* usually is a linked-list of all the parsed schema nodes */
3587 pnodes_p = substmt->storage;
3588 while (*pnodes_p) {
3589 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003590 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003591 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003592
3593 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003594 }
3595 case LY_STMT_BASE:
3596 case LY_STMT_BIT:
3597 case LY_STMT_DEFAULT:
3598 case LY_STMT_DEVIATE:
3599 case LY_STMT_DEVIATION:
3600 case LY_STMT_ENUM:
3601 case LY_STMT_EXTENSION:
3602 case LY_STMT_EXTENSION_INSTANCE:
3603 case LY_STMT_FEATURE:
3604 case LY_STMT_IDENTITY:
3605 case LY_STMT_IF_FEATURE:
3606 case LY_STMT_IMPORT:
3607 case LY_STMT_INCLUDE:
3608 case LY_STMT_MUST:
3609 case LY_STMT_PATTERN:
3610 case LY_STMT_REFINE:
3611 case LY_STMT_REVISION:
3612 case LY_STMT_TYPEDEF:
3613 case LY_STMT_UNIQUE:
3614 /* parse, sized array */
3615 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003616 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003617
3618 case LY_STMT_ARGUMENT:
3619 case LY_STMT_BELONGS_TO:
3620 case LY_STMT_CONTACT:
3621 case LY_STMT_DESCRIPTION:
3622 case LY_STMT_ERROR_APP_TAG:
3623 case LY_STMT_ERROR_MESSAGE:
3624 case LY_STMT_FRACTION_DIGITS:
3625 case LY_STMT_KEY:
3626 case LY_STMT_LENGTH:
3627 case LY_STMT_MANDATORY:
3628 case LY_STMT_MAX_ELEMENTS:
3629 case LY_STMT_MIN_ELEMENTS:
3630 case LY_STMT_MODIFIER:
3631 case LY_STMT_MODULE:
3632 case LY_STMT_NAMESPACE:
3633 case LY_STMT_ORGANIZATION:
3634 case LY_STMT_PATH:
3635 case LY_STMT_POSITION:
3636 case LY_STMT_PREFIX:
3637 case LY_STMT_PRESENCE:
3638 case LY_STMT_RANGE:
3639 case LY_STMT_REFERENCE:
3640 case LY_STMT_REQUIRE_INSTANCE:
3641 case LY_STMT_REVISION_DATE:
3642 case LY_STMT_SUBMODULE:
3643 case LY_STMT_TYPE:
3644 case LY_STMT_UNITS:
3645 case LY_STMT_VALUE:
3646 case LY_STMT_WHEN:
3647 case LY_STMT_YANG_VERSION:
3648 case LY_STMT_YIN_ELEMENT:
3649 /* single item */
3650 if (*(void **)substmt->storage) {
3651 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3652 rc = LY_EVALID;
3653 goto cleanup;
3654 }
3655
3656 /* parse */
3657 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003658 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003659
3660 case LY_STMT_CONFIG:
3661 /* single item */
3662 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3663 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3664 rc = LY_EVALID;
3665 goto cleanup;
3666 }
3667
3668 /* parse */
3669 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3670 break;
3671
3672 case LY_STMT_ORDERED_BY:
3673 /* single item */
3674 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3675 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3676 rc = LY_EVALID;
3677 goto cleanup;
3678 }
3679
3680 /* parse */
3681 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3682 break;
3683
3684 case LY_STMT_STATUS:
3685 /* single item */
3686 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3687 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3688 rc = LY_EVALID;
3689 goto cleanup;
3690 }
3691
3692 /* parse */
3693 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3694 break;
3695
Michal Vasko59892dd2022-05-13 11:02:30 +02003696 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003697 LOGINT(PARSER_CTX(pctx));
3698 rc = LY_EINT;
3699 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003700 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003701
3702cleanup:
3703 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003704}