blob: bdc8529a4b582be151e0bba32f9bdc4d13ebd6b8 [file] [log] [blame]
Radek Krejci335332a2019-09-05 13:03:35 +02001/**
Michal Vasko59892dd2022-05-13 11:02:30 +02002 * @file parser_common.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief libyang common parser functions.
Radek Krejci335332a2019-09-05 13:03:35 +02005 *
Michal Vasko59892dd2022-05-13 11:02:30 +02006 * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
Radek Krejci335332a2019-09-05 13:03:35 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Michal Vasko59892dd2022-05-13 11:02:30 +020015#define _GNU_SOURCE
16#define _POSIX_C_SOURCE 200809L /* strdup, strndup */
17
18#ifdef __APPLE__
19#define _DARWIN_C_SOURCE /* F_GETPATH */
20#endif
21
22#if defined (__NetBSD__) || defined (__OpenBSD__)
23/* realpath */
24#define _XOPEN_SOURCE 1
25#define _XOPEN_SOURCE_EXTENDED 1
26#endif
27
28#include "parser_internal.h"
29
Radek Krejci335332a2019-09-05 13:03:35 +020030#include <assert.h>
31#include <ctype.h>
32#include <errno.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020033#include <fcntl.h>
34#include <limits.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020035#include <stdint.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020036#include <stdio.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020037#include <stdlib.h>
38#include <string.h>
Michal Vasko59892dd2022-05-13 11:02:30 +020039#include <unistd.h>
Radek Krejci335332a2019-09-05 13:03:35 +020040
Radek Krejci535ea9f2020-05-29 16:01:05 +020041#include "common.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020042#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020043#include "dict.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020044#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010045#include "log.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020046#include "parser_data.h"
Michal Vasko69730152020-10-09 16:30:07 +020047#include "path.h"
Michal Vaskob4750962022-10-06 15:33:35 +020048#include "plugins_exts/metadata.h"
Michal 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) {
105 LOGVAL_ERRITEM(ctx, err);
106 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
222 LOG_LOCSET(snode, NULL, NULL, NULL);
223
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:
277 LOG_LOCBACK(1, 0, 0, 0);
278 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 Vasko9dbb91d2023-01-30 13:59:22 +0100288 if ((r = lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node))) {
289 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{
307 ly_bool incomplete;
308 struct lyd_meta *first = NULL;
309
310 if (meta && *meta) {
311 /* remember the first metadata */
312 first = *meta;
313 }
314
315 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
316 hints, ctx_node, 0, &incomplete));
317
318 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
319 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
320 }
321
322 if (first) {
323 /* always return the first metadata */
324 *meta = first;
325 }
326
327 return LY_SUCCESS;
328}
329
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200330LY_ERR
331lyd_parse_check_keys(struct lyd_node *node)
332{
333 const struct lysc_node *skey = NULL;
334 const struct lyd_node *key;
335
336 assert(node->schema->nodetype == LYS_LIST);
337
338 key = lyd_child(node);
339 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
340 if (!key || (key->schema != skey)) {
341 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
342 return LY_EVALID;
343 }
344
345 key = key->next;
346 }
347
348 return LY_SUCCESS;
349}
350
351LY_ERR
352lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
353 struct lysc_ext_instance *ext)
354{
355 struct lyd_meta *meta2, *prev_meta = NULL;
356 struct lyd_ctx_ext_val *ext_val;
357
Michal Vaskobc9f76f2022-12-01 10:31:38 +0100358 if (lydctx->parse_opts & LYD_PARSE_NO_NEW) {
359 node->flags &= ~LYD_NEW;
360 }
361
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200362 if (lysc_has_when(node->schema)) {
Michal Vaskofbb48c22022-11-30 13:28:03 +0100363 if (lydctx->parse_opts & LYD_PARSE_WHEN_TRUE) {
364 /* the condition was true before */
365 node->flags |= LYD_WHEN_TRUE;
366 }
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200367 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
368 /* remember we need to evaluate this node's when */
369 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
370 }
371 }
372
373 LY_LIST_FOR(*meta, meta2) {
374 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
375 meta2->value.boolean) {
376 /* node is default according to the metadata */
377 node->flags |= LYD_DEFAULT;
378
379 /* delete the metadata */
380 if (prev_meta) {
381 prev_meta->next = meta2->next;
Michal Vasko4754d4a2022-12-01 10:11:21 +0100382 } else if (meta != &node->meta) {
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200383 *meta = (*meta)->next;
384 }
385 lyd_free_meta_single(meta2);
Michal Vasko4754d4a2022-12-01 10:11:21 +0100386
387 /* update dflt flag for all parent NP containers */
388 lyd_cont_set_dflt(lyd_parent(node));
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200389 break;
390 }
391
392 prev_meta = meta2;
393 }
394
395 if (ext) {
396 /* parsed for an extension */
397 node->flags |= LYD_EXT;
398
399 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
400 /* rememeber for validation */
401 ext_val = malloc(sizeof *ext_val);
402 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
403 ext_val->ext = ext;
404 ext_val->sibling = node;
405 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
406 }
407 }
408
409 return LY_SUCCESS;
410}
411
Michal Vasko193dacd2022-10-13 08:43:05 +0200412void
413lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
414{
415 char path[PATH_MAX];
416
417#ifndef __APPLE__
418 char proc_path[32];
419 int len;
420#endif
421
422 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
423 if (*filepath) {
424 /* filepath already set */
425 return;
426 }
427
428 switch (in->type) {
429 case LY_IN_FILEPATH:
430 if (realpath(in->method.fpath.filepath, path) != NULL) {
431 lydict_insert(ctx, path, 0, filepath);
432 } else {
433 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
434 }
435
436 break;
437 case LY_IN_FD:
438#ifdef __APPLE__
439 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
440 lydict_insert(ctx, path, 0, filepath);
441 }
442#elif defined _WIN32
443 HANDLE h = _get_osfhandle(in->method.fd);
444 FILE_NAME_INFO info;
Michal Vasko2bf4af42023-01-04 12:08:38 +0100445
Michal Vasko193dacd2022-10-13 08:43:05 +0200446 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
447 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
Michal Vasko2bf4af42023-01-04 12:08:38 +0100448
Michal Vasko193dacd2022-10-13 08:43:05 +0200449 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
450 lydict_insert(ctx, buf, len, filepath);
451 }
452#else
453 /* get URI if there is /proc */
454 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
455 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
456 lydict_insert(ctx, path, len, filepath);
457 }
458#endif
459 break;
460 case LY_IN_MEMORY:
461 case LY_IN_FILE:
462 /* nothing to do */
463 break;
464 default:
465 LOGINT(ctx);
466 break;
467 }
468}
469
Michal Vaskod0625d72022-10-06 15:02:50 +0200470static 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 +0100471 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200472static 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 +0100473 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200474static 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 +0100475 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200476static 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 +0100477 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200478static 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 +0100479 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200480static 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 +0100481 struct lysp_node **siblings);
482
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100483/**
484 * @brief Validate stmt string value.
485 *
486 * @param[in] ctx Parser context.
487 * @param[in] val_type String value type.
488 * @param[in] val Value to validate.
489 * @return LY_ERR value.
490 */
Radek Krejci335332a2019-09-05 13:03:35 +0200491static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200492lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200493{
Radek Krejci857189e2020-09-01 13:26:36 +0200494 uint8_t prefix = 0;
495 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200496 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200497 size_t utf8_char_len;
498
Michal Vaskocfa1a962023-02-27 09:28:45 +0100499 if (!val) {
500 if (val_type == Y_MAYBE_STR_ARG) {
501 /* fine */
502 return LY_SUCCESS;
503 }
504
505 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Missing an expected string.");
506 return LY_EVALID;
507 }
508
Radek Krejci335332a2019-09-05 13:03:35 +0200509 while (*val) {
510 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200511 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200512
513 switch (val_type) {
514 case Y_IDENTIF_ARG:
515 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
516 break;
517 case Y_PREF_IDENTIF_ARG:
518 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
519 break;
520 case Y_STR_ARG:
521 case Y_MAYBE_STR_ARG:
522 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
523 break;
524 }
525 first = 0;
526 }
527
528 return LY_SUCCESS;
529}
530
531/**
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100532 * @brief Duplicate statement siblings, recursively.
533 *
534 * @param[in] ctx Parser context.
535 * @param[in] stmt Statement to duplicate.
536 * @param[out] first First duplicated statement, the rest follow.
537 * @return LY_ERR value.
538 */
539static LY_ERR
540lysp_stmt_dup(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_stmt **first)
541{
542 struct lysp_stmt *child, *last = NULL;
543
544 LY_LIST_FOR(stmt, stmt) {
545 child = calloc(1, sizeof *child);
546 LY_CHECK_ERR_RET(!child, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
547
548 if (last) {
549 last->next = child;
550 } else {
551 assert(!*first);
552 *first = child;
553 }
554 last = child;
555
556 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &child->stmt));
557 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &child->arg));
558 child->format = stmt->format;
559 LY_CHECK_RET(ly_dup_prefix_data(PARSER_CTX(ctx), stmt->format, stmt->prefix_data, &child->prefix_data));
560 child->flags = stmt->flags;
561 child->kw = stmt->kw;
562
563 /* recursively */
564 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &child->child));
565 }
566
567 return LY_SUCCESS;
568}
569
570/**
Radek Krejci335332a2019-09-05 13:03:35 +0200571 * @brief Parse extension instance.
572 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100573 * @param[in] ctx parser context.
574 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100575 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200576 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
577 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200578 * @return LY_ERR values.
579 */
580static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200581lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200582 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200583{
584 struct lysp_ext_instance *e;
585
Michal Vaskob36053d2020-03-26 15:49:30 +0100586 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200587
588 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200589 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100590 e->parent_stmt = insubstmt;
591 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200592 e->parsed = NULL;
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100593 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &e->child));
Radek Krejci335332a2019-09-05 13:03:35 +0200594
595 /* get optional argument */
596 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200597 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200598 }
599
600 return LY_SUCCESS;
601}
602
603/**
604 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
605 * description, etc...
606 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100607 * @param[in] ctx parser context.
608 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200609 * @param[in] substmt_index Index of this substatement.
610 * @param[in,out] value Place to store the parsed value.
611 * @param[in] arg Type of the YANG keyword argument (of the value).
612 * @param[in,out] exts Extension instances to add to.
613 *
614 * @return LY_ERR values.
615 */
616static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200617lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
618 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200619{
Radek Krejci335332a2019-09-05 13:03:35 +0200620 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200621 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200622 return LY_EVALID;
623 }
624
625 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200626 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200627
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100628 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
629 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200630 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100631 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200632 break;
633 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200634 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200635 return LY_EVALID;
636 }
637 }
638 return LY_SUCCESS;
639}
640
641/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200642 * @brief Parse a qname that can have more instances such as if-feature.
643 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100644 * @param[in] ctx parser context.
645 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200646 * @param[in,out] qnames Parsed qnames to add to.
647 * @param[in] arg Type of the expected argument.
648 * @param[in,out] exts Extension instances to add to.
649 *
650 * @return LY_ERR values.
651 */
652static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200653lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
654 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200655{
656 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200657
658 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
659
660 /* allocate new pointer */
661 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
662 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100663 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200664
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100665 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
666 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200667 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100668 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200669 break;
670 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200671 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200672 return LY_EVALID;
673 }
674 }
675 return LY_SUCCESS;
676}
677
678/**
Radek Krejci335332a2019-09-05 13:03:35 +0200679 * @brief Parse a generic text field that can have more instances such as base.
680 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100681 * @param[in] ctx parser context.
682 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200683 * @param[in,out] texts Parsed values to add to.
684 * @param[in] arg Type of the expected argument.
685 * @param[in,out] exts Extension instances to add to.
686 *
687 * @return LY_ERR values.
688 */
689static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200690lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
691 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200692{
693 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200694
695 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
696
697 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100698 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200699 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200700
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100701 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
702 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200703 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100704 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200705 break;
706 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200707 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200708 return LY_EVALID;
709 }
710 }
711 return LY_SUCCESS;
712}
713
714/**
715 * @brief Parse the status statement.
716 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100717 * @param[in] ctx parser context.
718 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200719 * @param[in,out] flags Flags to add to.
720 * @param[in,out] exts Extension instances to add to.
721 *
722 * @return LY_ERR values.
723 */
724static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200725lysp_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 +0200726{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200727 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200728
729 if (*flags & LYS_STATUS_MASK) {
730 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
731 return LY_EVALID;
732 }
733
734 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
735 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100736 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200737 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100738 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200739 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100740 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200741 *flags |= LYS_STATUS_OBSLT;
742 } else {
743 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
744 return LY_EVALID;
745 }
746
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100747 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
748 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200749 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100750 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200751 break;
752 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200753 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200754 return LY_EVALID;
755 }
756 }
757 return LY_SUCCESS;
758}
759
760/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100761 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200762 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100763 * @param[in] ctx parser context.
764 * @param[in] stmt Source statement data from the parsed extension instance.
765 * @param[in,out] when_p When pointer to parse to.
766 *
767 * @return LY_ERR values.
768 */
769static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200770lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100771{
772 LY_ERR ret = LY_SUCCESS;
773 struct lysp_when *when;
774
775 if (*when_p) {
776 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
777 return LY_EVALID;
778 }
779
780 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
781
782 when = calloc(1, sizeof *when);
783 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
784 *when_p = when;
785
786 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
787
788 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
789 switch (child->kw) {
790 case LY_STMT_DESCRIPTION:
791 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
792 break;
793 case LY_STMT_REFERENCE:
794 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
795 break;
796 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100797 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100798 break;
799 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200800 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100801 return LY_EVALID;
802 }
803 }
804 return ret;
805}
806
807/**
808 * @brief Parse the config statement.
809 *
810 * @param[in] ctx parser context.
811 * @param[in] stmt Source statement data from the parsed extension instance.
812 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200813 * @param[in,out] exts Extension instances to add to.
814 *
815 * @return LY_ERR values.
816 */
817static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200818lysp_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 +0200819{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200820 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200821
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100822 if (*flags & LYS_CONFIG_MASK) {
823 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
824 return LY_EVALID;
825 }
826
827 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
828 arg_len = strlen(stmt->arg);
829 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
830 *flags |= LYS_CONFIG_W;
831 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
832 *flags |= LYS_CONFIG_R;
833 } else {
834 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
835 return LY_EVALID;
836 }
837
838 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
839 switch (child->kw) {
840 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100841 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100842 break;
843 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200844 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100845 return LY_EVALID;
846 }
847 }
848
849 return LY_SUCCESS;
850}
851
852/**
853 * @brief Parse the mandatory statement.
854 *
855 * @param[in] ctx parser context.
856 * @param[in] stmt Source statement data from the parsed extension instance.
857 * @param[in,out] flags Flags to add to.
858 * @param[in,out] exts Extension instances to add to.
859 *
860 * @return LY_ERR values.
861 */
862static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200863lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200864 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100865{
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200866 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100867
868 if (*flags & LYS_MAND_MASK) {
869 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
870 return LY_EVALID;
871 }
872
873 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
874 arg_len = strlen(stmt->arg);
875 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
876 *flags |= LYS_MAND_TRUE;
877 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
878 *flags |= LYS_MAND_FALSE;
879 } else {
880 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
881 return LY_EVALID;
882 }
883
884 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
885 switch (child->kw) {
886 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100887 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100888 break;
889 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200890 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100891 return LY_EVALID;
892 }
893 }
894
895 return LY_SUCCESS;
896}
897
898/**
899 * @brief Parse a restriction such as range or length.
900 *
901 * @param[in] ctx parser context.
902 * @param[in] stmt Source statement data from the parsed extension instance.
903 * @param[in,out] exts Extension instances to add to.
904 *
905 * @return LY_ERR values.
906 */
907static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200908lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100909{
Radek Krejci335332a2019-09-05 13:03:35 +0200910 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200911 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100912 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200913
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100914 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
915 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200916 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100917 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200918 break;
919 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100920 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200921 break;
922 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100923 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200924 break;
925 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100926 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200927 break;
928 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100929 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200930 break;
931 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200932 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200933 return LY_EVALID;
934 }
935 }
936 return LY_SUCCESS;
937}
938
939/**
940 * @brief Parse a restriction that can have more instances such as must.
941 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100942 * @param[in] ctx parser context.
943 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200944 * @param[in,out] restrs Restrictions to add to.
945 *
946 * @return LY_ERR values.
947 */
948static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200949lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200950{
951 struct lysp_restr *restr;
952
Michal Vaskob36053d2020-03-26 15:49:30 +0100953 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100954 return lysp_stmt_restr(ctx, stmt, restr);
955}
956
957/**
958 * @brief Parse the anydata or anyxml statement.
959 *
960 * @param[in] ctx parser context.
961 * @param[in] stmt Source statement data from the parsed extension instance.
962 * @param[in,out] siblings Siblings to add to.
963 *
964 * @return LY_ERR values.
965 */
966static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200967lysp_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 +0100968{
969 struct lysp_node_anydata *any;
970
971 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
972
973 /* create new structure and insert into siblings */
974 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
975
976 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
977 any->parent = parent;
978
979 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
980
981 /* parse substatements */
982 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
983 switch (child->kw) {
984 case LY_STMT_CONFIG:
985 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
986 break;
987 case LY_STMT_DESCRIPTION:
988 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
989 break;
990 case LY_STMT_IF_FEATURE:
991 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
992 break;
993 case LY_STMT_MANDATORY:
994 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
995 break;
996 case LY_STMT_MUST:
997 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
998 break;
999 case LY_STMT_REFERENCE:
1000 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
1001 break;
1002 case LY_STMT_STATUS:
1003 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
1004 break;
1005 case LY_STMT_WHEN:
1006 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
1007 break;
1008 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001009 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001010 break;
1011 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001012 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1013 (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 +01001014 return LY_EVALID;
1015 }
1016 }
1017
1018 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +02001019}
1020
1021/**
1022 * @brief Parse the value or position statement. Substatement of type enum statement.
1023 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001024 * @param[in] ctx parser context.
1025 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001026 * @param[in,out] value Value to write to.
1027 * @param[in,out] flags Flags to write to.
1028 * @param[in,out] exts Extension instances to add to.
1029 *
1030 * @return LY_ERR values.
1031 */
1032static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001033lysp_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 +02001034 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001035{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001036 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001037 char *ptr = NULL;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001038 long long num = 0;
1039 unsigned long long unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +02001040
1041 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001042 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001043 return LY_EVALID;
1044 }
1045 *flags |= LYS_SET_VALUE;
1046
1047 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1048
1049 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001050 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
1051 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001052 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001053 goto error;
1054 }
1055
1056 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001057 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001058 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001059 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001060 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001061 goto error;
1062 }
1063 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001064 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001065 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001066 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001067 goto error;
1068 }
1069 }
1070 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001071 if (ptr - stmt->arg != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001072 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001073 goto error;
1074 }
1075 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001076 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001077 goto error;
1078 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001079 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +02001080 *value = num;
1081 } else {
1082 *value = unum;
1083 }
1084
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001085 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1086 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001087 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001088 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 +02001089 break;
1090 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001091 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001092 return LY_EVALID;
1093 }
1094 }
1095 return LY_SUCCESS;
1096
1097error:
1098 return LY_EVALID;
1099}
1100
1101/**
1102 * @brief Parse the enum or bit statement. Substatement of type statement.
1103 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001104 * @param[in] ctx parser context.
1105 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001106 * @param[in,out] enums Enums or bits to add to.
1107 *
1108 * @return LY_ERR values.
1109 */
1110static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001111lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +02001112{
1113 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +02001114
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001115 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 +02001116
Michal Vaskob36053d2020-03-26 15:49:30 +01001117 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001118
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001119 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +02001120 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
1121 } /* else nothing specific for YANG_BIT */
1122
Radek Krejci011e4aa2020-09-04 15:22:31 +02001123 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +02001124 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +02001125
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001126 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1127 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001128 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001129 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001130 break;
1131 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001132 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001133 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001134 break;
1135 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001136 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001137 break;
1138 case LY_STMT_STATUS:
1139 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
1140 break;
1141 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001142 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1143 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001144 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001145 break;
1146 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +02001147 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1148 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001149 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001150 break;
1151 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001152 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001153 break;
1154 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001155 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001156 return LY_EVALID;
1157 }
1158 }
Michal Vasko193dacd2022-10-13 08:43:05 +02001159
Radek Krejci335332a2019-09-05 13:03:35 +02001160 return LY_SUCCESS;
1161}
1162
1163/**
1164 * @brief Parse the fraction-digits statement. Substatement of type statement.
1165 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001166 * @param[in] ctx parser context.
1167 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001168 * @param[in,out] fracdig Value to write to.
1169 * @param[in,out] exts Extension instances to add to.
1170 *
1171 * @return LY_ERR values.
1172 */
1173static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001174lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001175 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001176{
1177 char *ptr;
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001178 int arg_len;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001179 unsigned long long num;
Radek Krejci335332a2019-09-05 13:03:35 +02001180
1181 if (*fracdig) {
1182 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1183 return LY_EVALID;
1184 }
1185
1186 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1187 arg_len = strlen(stmt->arg);
1188 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1189 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1190 return LY_EVALID;
1191 }
1192
1193 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001194 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001195 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001196 if (ptr - stmt->arg != arg_len) {
Radek Krejci335332a2019-09-05 13:03:35 +02001197 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1198 return LY_EVALID;
1199 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001200 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001201 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1202 return LY_EVALID;
1203 }
1204 *fracdig = num;
1205
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001206 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1207 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001208 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001209 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001210 break;
1211 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001212 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001213 return LY_EVALID;
1214 }
1215 }
1216 return LY_SUCCESS;
1217}
1218
1219/**
1220 * @brief Parse the require-instance statement. Substatement of type statement.
1221 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001222 * @param[in] ctx parser context.
1223 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001224 * @param[in,out] reqinst Value to write to.
1225 * @param[in,out] flags Flags to write to.
1226 * @param[in,out] exts Extension instances to add to.
1227 *
1228 * @return LY_ERR values.
1229 */
1230static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001231lysp_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 +02001232 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001233{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001234 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001235
1236 if (*flags & LYS_SET_REQINST) {
1237 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1238 return LY_EVALID;
1239 }
1240 *flags |= LYS_SET_REQINST;
1241
1242 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1243 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001244 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001245 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001246 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001247 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1248 return LY_EVALID;
1249 }
1250
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001251 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1252 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001253 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001254 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001255 break;
1256 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001257 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001258 return LY_EVALID;
1259 }
1260 }
1261 return LY_SUCCESS;
1262}
1263
1264/**
1265 * @brief Parse the modifier statement. Substatement of type pattern statement.
1266 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001267 * @param[in] ctx parser context.
1268 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001269 * @param[in,out] pat Value to write to.
1270 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001271 * @return LY_ERR values.
1272 */
1273static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001274lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001275 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001276{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001277 int arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001278 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001279
Radek Krejcif13b87b2020-12-01 22:02:17 +01001280 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001281 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1282 return LY_EVALID;
1283 }
1284
1285 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1286 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001287 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001288 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1289 return LY_EVALID;
1290 }
1291
1292 /* replace the value in the dictionary */
1293 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001294 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001295 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001296 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001297
Radek Krejcif13b87b2020-12-01 22:02:17 +01001298 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1299 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001300 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001301
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001302 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1303 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001304 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001305 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001306 break;
1307 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001308 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001309 return LY_EVALID;
1310 }
1311 }
1312 return LY_SUCCESS;
1313}
1314
1315/**
1316 * @brief Parse the pattern statement. Substatement of type statement.
1317 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001318 * @param[in] ctx parser context.
1319 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001320 * @param[in,out] patterns Restrictions to add to.
1321 *
1322 * @return LY_ERR values.
1323 */
1324static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001325lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001326{
1327 char *buf;
1328 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001329 struct lysp_restr *restr;
1330
1331 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001332 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001333 arg_len = strlen(stmt->arg);
1334
1335 /* add special meaning first byte */
1336 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001337 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001338 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001339 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001340 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001341 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001342 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001343
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001344 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1345 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001346 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001347 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001348 break;
1349 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001350 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001351 break;
1352 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001353 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001354 break;
1355 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001356 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001357 break;
1358 case LY_STMT_MODIFIER:
1359 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001360 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001361 break;
1362 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001363 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001364 break;
1365 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001366 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001367 return LY_EVALID;
1368 }
1369 }
1370 return LY_SUCCESS;
1371}
1372
1373/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001374 * @brief Parse the deviate statement. Substatement of deviation statement.
1375 *
1376 * @param[in] ctx parser context.
1377 * @param[in] stmt Source statement data from the parsed extension instance.
1378 * @param[in,out] devs Array of deviates to add to.
1379 * @param[in,out] exts Extension instances to add to.
1380 * @return LY_ERR values.
1381 */
1382static LY_ERR
1383lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1384{
1385 (void)stmt;
1386 (void)devs;
1387 (void)exts;
1388
1389 /* TODO */
1390 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1391 return LY_EINVAL;
1392}
1393
1394/**
1395 * @brief Parse the deviation statement.
1396 *
1397 * @param[in] ctx parser context.
1398 * @param[in] stmt Source statement data from the parsed extension instance.
1399 * @param[in,out] deviations Array of deviations to add to.
1400 * @return LY_ERR values.
1401 */
1402static LY_ERR
1403lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1404{
1405 struct lysp_deviation *dev;
1406
1407 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1408
1409 /* store nodeid */
1410 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1411 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1412
1413 /* parse substatements */
1414 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1415 switch (child->kw) {
1416 case LY_STMT_DESCRIPTION:
1417 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1418 break;
1419 case LY_STMT_DEVIATE:
1420 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1421 break;
1422 case LY_STMT_REFERENCE:
1423 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1424 break;
1425 case LY_STMT_EXTENSION_INSTANCE:
1426 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1427 break;
1428 default:
1429 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1430 return LY_EVALID;
1431 }
1432 }
1433
1434 return LY_SUCCESS;
1435}
1436
1437/**
1438 * @brief Parse the yang-version statement.
1439 *
1440 * @param[in] ctx parser context.
1441 * @param[in] stmt Source statement data from the parsed extension instance.
1442 * @param[out] version Version to write to.
1443 * @param[in,out] exts Extension instances to add to.
1444 * @return LY_ERR values.
1445 */
1446static LY_ERR
1447lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1448{
1449 if (*version) {
1450 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1451 return LY_EVALID;
1452 }
1453
1454 /* store flag */
1455 if (!strcmp(stmt->arg, "1")) {
1456 *version = LYS_VERSION_1_0;
1457 } else if (!strcmp(stmt->arg, "1.1")) {
1458 *version = LYS_VERSION_1_1;
1459 } else {
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001460 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, (int)strlen(stmt->arg), stmt->arg, "yang-version");
Michal Vasko193dacd2022-10-13 08:43:05 +02001461 return LY_EVALID;
1462 }
1463
1464 /* parse substatements */
1465 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1466 switch (child->kw) {
1467 case LY_STMT_EXTENSION_INSTANCE:
1468 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1469 break;
1470 default:
1471 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1472 return LY_EVALID;
1473 }
1474 }
1475
1476 return LY_SUCCESS;
1477}
1478
1479/**
1480 * @brief Parse the module statement.
1481 *
1482 * @param[in] ctx parser context.
1483 * @param[in] stmt Source statement data from the parsed extension instance.
1484 * @param[in,out] mod Module to fill.
1485 * @return LY_ERR values.
1486 */
1487static LY_ERR
1488lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1489{
1490 (void)stmt;
1491 (void)mod;
1492
1493 /* TODO */
1494 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1495 return LY_EINVAL;
1496}
1497
1498/**
1499 * @brief Parse the submodule statement.
1500 *
1501 * @param[in] ctx parser context.
1502 * @param[in] stmt Source statement data from the parsed extension instance.
1503 * @param[in,out] submod Module to fill.
1504 * @return LY_ERR values.
1505 */
1506static LY_ERR
1507lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1508{
1509 (void)stmt;
1510 (void)submod;
1511
1512 /* TODO */
1513 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1514 return LY_EINVAL;
1515}
1516
1517/**
1518 * @brief Parse the yin-element statement. Substatement of argument statement.
1519 *
1520 * @param[in] ctx parser context.
1521 * @param[in] stmt Source statement data from the parsed extension instance.
1522 * @param[in,out] flags Flags to write to.
1523 * @param[in,out] exts Extension instances to add to.
1524 * @return LY_ERR values.
1525 */
1526static LY_ERR
1527lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1528{
1529 if (*flags & LYS_YINELEM_MASK) {
1530 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1531 return LY_EVALID;
1532 }
1533
1534 /* store flag */
1535 if (!strcmp(stmt->arg, "true")) {
1536 *flags |= LYS_YINELEM_TRUE;
1537 } else if (!strcmp(stmt->arg, "false")) {
1538 *flags |= LYS_YINELEM_FALSE;
1539 } else {
Michal Vasko7b3a00e2023-08-09 11:58:03 +02001540 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, (int)strlen(stmt->arg), stmt->arg, "yin-element");
Michal Vasko193dacd2022-10-13 08:43:05 +02001541 return LY_EVALID;
1542 }
1543
1544 /* parse substatements */
1545 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1546 switch (child->kw) {
1547 case LY_STMT_EXTENSION_INSTANCE:
1548 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1549 break;
1550 default:
1551 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1552 return LY_EVALID;
1553 }
1554 }
1555
1556 return LY_SUCCESS;
1557}
1558
1559/**
1560 * @brief Parse the argument statement. Substatement of extension statement.
1561 *
1562 * @param[in] ctx parser context.
1563 * @param[in] stmt Source statement data from the parsed extension instance.
1564 * @param[in,out] ex Extension to fill.
1565 * @return LY_ERR values.
1566 */
1567static LY_ERR
1568lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1569{
1570 if (ex->argname) {
1571 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1572 return LY_EVALID;
1573 }
1574
1575 /* store argument name */
1576 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1577 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1578
1579 /* parse substatements */
1580 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1581 switch (child->kw) {
1582 case LY_STMT_YIN_ELEMENT:
1583 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1584 break;
1585 case LY_STMT_EXTENSION_INSTANCE:
1586 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1587 break;
1588 default:
1589 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1590 return LY_EVALID;
1591 }
1592 }
1593
1594 return LY_SUCCESS;
1595}
1596
1597/**
1598 * @brief Parse the extension statement.
1599 *
1600 * @param[in] ctx parser context.
1601 * @param[in] stmt Source statement data from the parsed extension instance.
1602 * @param[in,out] extensions Array of extensions to add to.
1603 * @return LY_ERR values.
1604 */
1605static LY_ERR
1606lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1607{
1608 struct lysp_ext *ex;
1609
1610 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1611
1612 /* store name */
1613 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1614 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1615
1616 /* parse substatements */
1617 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1618 switch (child->kw) {
1619 case LY_STMT_DESCRIPTION:
1620 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1621 break;
1622 case LY_STMT_REFERENCE:
1623 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1624 break;
1625 case LY_STMT_STATUS:
1626 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1627 break;
1628 case LY_STMT_ARGUMENT:
1629 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1630 break;
1631 case LY_STMT_EXTENSION_INSTANCE:
1632 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1633 break;
1634 default:
1635 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1636 return LY_EVALID;
1637 }
1638 }
1639
1640 return LY_SUCCESS;
1641}
1642
1643/**
1644 * @brief Parse the feature statement.
1645 *
1646 * @param[in] ctx parser context.
1647 * @param[in] stmt Source statement data from the parsed extension instance.
1648 * @param[in,out] features Array of features to add to.
1649 * @return LY_ERR values.
1650 */
1651static LY_ERR
1652lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1653{
1654 struct lysp_feature *feat;
1655
1656 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1657
1658 /* store name */
1659 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1660 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1661
1662 /* parse substatements */
1663 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1664 switch (child->kw) {
1665 case LY_STMT_DESCRIPTION:
1666 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1667 break;
1668 case LY_STMT_IF_FEATURE:
1669 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1670 break;
1671 case LY_STMT_REFERENCE:
1672 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1673 break;
1674 case LY_STMT_STATUS:
1675 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1676 break;
1677 case LY_STMT_EXTENSION_INSTANCE:
1678 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1679 break;
1680 default:
1681 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1682 return LY_EVALID;
1683 }
1684 }
1685
1686 return LY_SUCCESS;
1687}
1688
1689/**
1690 * @brief Parse the identity statement.
1691 *
1692 * @param[in] ctx parser context.
1693 * @param[in] stmt Source statement data from the parsed extension instance.
1694 * @param[in,out] identities Array of identities to add to.
1695 * @return LY_ERR values.
1696 */
1697static LY_ERR
1698lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1699{
1700 struct lysp_ident *ident;
1701
1702 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1703
1704 /* store name */
1705 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1706 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1707
1708 /* parse substatements */
1709 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1710 switch (child->kw) {
1711 case LY_STMT_DESCRIPTION:
1712 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1713 break;
1714 case LY_STMT_IF_FEATURE:
1715 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1716 break;
1717 case LY_STMT_REFERENCE:
1718 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1719 break;
1720 case LY_STMT_STATUS:
1721 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1722 break;
1723 case LY_STMT_BASE:
1724 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1725 break;
1726 case LY_STMT_EXTENSION_INSTANCE:
1727 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1728 break;
1729 default:
1730 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1731 return LY_EVALID;
1732 }
1733 }
1734
1735 return LY_SUCCESS;
1736}
1737
1738/**
1739 * @brief Parse the import statement.
1740 *
1741 * @param[in] ctx parser context.
1742 * @param[in] stmt Source statement data from the parsed extension instance.
1743 * @param[in,out] imports Array of imports to add to.
1744 * @return LY_ERR values.
1745 */
1746static LY_ERR
1747lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1748{
1749 struct lysp_import *imp;
1750 const char *str = NULL;
1751
1752 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1753
1754 /* store name */
1755 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1756 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1757
1758 /* parse substatements */
1759 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1760 switch (child->kw) {
1761 case LY_STMT_PREFIX:
1762 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1763 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1764 break;
1765 case LY_STMT_DESCRIPTION:
1766 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1767 break;
1768 case LY_STMT_REFERENCE:
1769 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1770 break;
1771 case LY_STMT_REVISION_DATE:
1772 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1773 strcpy(imp->rev, str);
1774 lydict_remove(PARSER_CTX(ctx), str);
1775 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1776 break;
1777 case LY_STMT_EXTENSION_INSTANCE:
1778 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1779 break;
1780 default:
1781 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1782 return LY_EVALID;
1783 }
1784 }
1785
1786 return LY_SUCCESS;
1787}
1788
1789/**
1790 * @brief Parse the include statement.
1791 *
1792 * @param[in] ctx parser context.
1793 * @param[in] stmt Source statement data from the parsed extension instance.
1794 * @param[in,out] includes Array of identities to add to.
1795 * @return LY_ERR values.
1796 */
1797static LY_ERR
1798lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1799{
1800 struct lysp_include *inc;
1801 const char *str = NULL;
1802
1803 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1804
1805 /* store name */
1806 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1807 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1808
1809 /* parse substatements */
1810 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1811 switch (child->kw) {
1812 case LY_STMT_DESCRIPTION:
1813 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1814 break;
1815 case LY_STMT_REFERENCE:
1816 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1817 break;
1818 case LY_STMT_REVISION_DATE:
1819 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1820 strcpy(inc->rev, str);
1821 lydict_remove(PARSER_CTX(ctx), str);
1822 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1823 break;
1824 case LY_STMT_EXTENSION_INSTANCE:
1825 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1826 break;
1827 default:
1828 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1829 return LY_EVALID;
1830 }
1831 }
1832
1833 return LY_SUCCESS;
1834}
1835
1836/**
1837 * @brief Parse the revision statement.
1838 *
1839 * @param[in] ctx parser context.
1840 * @param[in] stmt Source statement data from the parsed extension instance.
1841 * @param[in,out] includes Array of identities to add to.
1842 * @return LY_ERR values.
1843 */
1844static LY_ERR
1845lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1846{
1847 struct lysp_revision *rev;
1848
1849 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1850
1851 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001852 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001853 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001854
1855 /* parse substatements */
1856 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1857 switch (child->kw) {
1858 case LY_STMT_DESCRIPTION:
1859 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1860 break;
1861 case LY_STMT_REFERENCE:
1862 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1863 break;
1864 case LY_STMT_EXTENSION_INSTANCE:
1865 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1866 break;
1867 default:
1868 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1869 return LY_EVALID;
1870 }
1871 }
1872
1873 return LY_SUCCESS;
1874}
1875
1876/**
Radek Krejci335332a2019-09-05 13:03:35 +02001877 * @brief Parse the type statement.
1878 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001879 * @param[in] ctx parser context.
1880 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001881 * @param[in,out] type Type to wrote to.
1882 *
1883 * @return LY_ERR values.
1884 */
1885static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001886lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001887{
1888 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001889 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001890 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001891
1892 if (type->name) {
1893 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1894 return LY_EVALID;
1895 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001896
1897 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001898 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001899 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001900
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001901 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1902 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001903 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001904 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001905 type->flags |= LYS_SET_BASE;
1906 break;
1907 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001908 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001909 type->flags |= LYS_SET_BIT;
1910 break;
1911 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001912 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001913 type->flags |= LYS_SET_ENUM;
1914 break;
1915 case LY_STMT_FRACTION_DIGITS:
1916 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1917 type->flags |= LYS_SET_FRDIGITS;
1918 break;
1919 case LY_STMT_LENGTH:
1920 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001921 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001922 return LY_EVALID;
1923 }
1924 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001925 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001926
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001927 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001928 type->flags |= LYS_SET_LENGTH;
1929 break;
1930 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001931 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001932 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001933 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001934 lydict_remove(PARSER_CTX(ctx), str_path);
1935 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001936 type->flags |= LYS_SET_PATH;
1937 break;
1938 case LY_STMT_PATTERN:
1939 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1940 type->flags |= LYS_SET_PATTERN;
1941 break;
1942 case LY_STMT_RANGE:
1943 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001944 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001945 return LY_EVALID;
1946 }
1947 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001948 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001949
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001950 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001951 type->flags |= LYS_SET_RANGE;
1952 break;
1953 case LY_STMT_REQUIRE_INSTANCE:
1954 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001955 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001956 break;
1957 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001958 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001959 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1960 type->flags |= LYS_SET_TYPE;
1961 break;
1962 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001963 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001964 break;
1965 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001966 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001967 return LY_EVALID;
1968 }
1969 }
1970 return LY_SUCCESS;
1971}
1972
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001973/**
1974 * @brief Parse the leaf statement.
1975 *
1976 * @param[in] ctx parser context.
1977 * @param[in] stmt Source statement data from the parsed extension instance.
1978 * @param[in] parent Parent node to connect to (not into).
1979 * @param[in,out] siblings Siblings to add to.
1980 *
1981 * @return LY_ERR values.
1982 */
1983static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001984lysp_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 +01001985{
1986 struct lysp_node_leaf *leaf;
1987
1988 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1989
1990 /* create new leaf structure */
1991 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1992 leaf->nodetype = LYS_LEAF;
1993 leaf->parent = parent;
1994
1995 /* get name */
1996 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1997
1998 /* parse substatements */
1999 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2000 switch (child->kw) {
2001 case LY_STMT_CONFIG:
2002 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
2003 break;
2004 case LY_STMT_DEFAULT:
2005 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 +01002006 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002007 break;
2008 case LY_STMT_DESCRIPTION:
2009 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
2010 break;
2011 case LY_STMT_IF_FEATURE:
2012 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
2013 break;
2014 case LY_STMT_MANDATORY:
2015 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
2016 break;
2017 case LY_STMT_MUST:
2018 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
2019 break;
2020 case LY_STMT_REFERENCE:
2021 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
2022 break;
2023 case LY_STMT_STATUS:
2024 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
2025 break;
2026 case LY_STMT_TYPE:
2027 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
2028 break;
2029 case LY_STMT_UNITS:
2030 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
2031 break;
2032 case LY_STMT_WHEN:
2033 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
2034 break;
2035 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002036 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002037 break;
2038 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002039 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002040 return LY_EVALID;
2041 }
2042 }
2043
2044 /* mandatory substatements */
2045 if (!leaf->type.name) {
2046 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
2047 return LY_EVALID;
2048 }
2049
2050 return LY_SUCCESS;
2051}
2052
2053/**
2054 * @brief Parse the max-elements statement.
2055 *
2056 * @param[in] ctx parser context.
2057 * @param[in] stmt Source statement data from the parsed extension instance.
2058 * @param[in,out] max Value to write to.
2059 * @param[in,out] flags Flags to write to.
2060 * @param[in,out] exts Extension instances to add to.
2061 *
2062 * @return LY_ERR values.
2063 */
2064static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002065lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
2066 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002067{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002068 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002069 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002070 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002071
2072 if (*flags & LYS_SET_MAX) {
2073 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
2074 return LY_EVALID;
2075 }
2076 *flags |= LYS_SET_MAX;
2077
2078 /* get value */
2079 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2080 arg_len = strlen(stmt->arg);
2081
2082 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
2083 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
2084 return LY_EVALID;
2085 }
2086
2087 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
2088 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002089 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002090 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002091 if (ptr - stmt->arg != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002092 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
2093 return LY_EVALID;
2094 }
2095 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2096 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
2097 return LY_EVALID;
2098 }
2099
2100 *max = num;
2101 } else {
2102 /* unbounded */
2103 *max = 0;
2104 }
2105
2106 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2107 switch (child->kw) {
2108 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002109 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002110 break;
2111 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002112 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002113 return LY_EVALID;
2114 }
2115 }
2116
2117 return LY_SUCCESS;
2118}
2119
2120/**
2121 * @brief Parse the min-elements statement.
2122 *
2123 * @param[in] ctx parser context.
2124 * @param[in] stmt Source statement data from the parsed extension instance.
2125 * @param[in,out] min Value to write to.
2126 * @param[in,out] flags Flags to write to.
2127 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002128 * @return LY_ERR values.
2129 */
2130static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002131lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
2132 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002133{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002134 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002135 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002136 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002137
2138 if (*flags & LYS_SET_MIN) {
2139 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
2140 return LY_EVALID;
2141 }
2142 *flags |= LYS_SET_MIN;
2143
2144 /* get value */
2145 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2146 arg_len = strlen(stmt->arg);
2147
2148 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
2149 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2150 return LY_EVALID;
2151 }
2152
2153 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002154 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002155 /* we have not parsed the whole argument */
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002156 if (ptr - stmt->arg != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002157 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2158 return LY_EVALID;
2159 }
2160 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2161 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
2162 return LY_EVALID;
2163 }
2164 *min = num;
2165
2166 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2167 switch (child->kw) {
2168 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002169 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002170 break;
2171 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002172 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002173 return LY_EVALID;
2174 }
2175 }
2176
2177 return LY_SUCCESS;
2178}
2179
2180/**
2181 * @brief Parse the ordered-by statement.
2182 *
2183 * @param[in] ctx parser context.
2184 * @param[in] stmt Source statement data from the parsed extension instance.
2185 * @param[in,out] flags Flags to write to.
2186 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002187 * @return LY_ERR values.
2188 */
2189static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002190lysp_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 +01002191{
Michal Vasko7b3a00e2023-08-09 11:58:03 +02002192 int arg_len;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002193
2194 if (*flags & LYS_ORDBY_MASK) {
2195 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2196 return LY_EVALID;
2197 }
2198
2199 /* get value */
2200 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2201 arg_len = strlen(stmt->arg);
2202 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2203 *flags |= LYS_MAND_TRUE;
2204 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2205 *flags |= LYS_MAND_FALSE;
2206 } else {
2207 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2208 return LY_EVALID;
2209 }
2210
2211 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2212 switch (child->kw) {
2213 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002214 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002215 break;
2216 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002217 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002218 return LY_EVALID;
2219 }
2220 }
2221
2222 return LY_SUCCESS;
2223}
2224
2225/**
2226 * @brief Parse the leaf-list statement.
2227 *
2228 * @param[in] ctx parser context.
2229 * @param[in] stmt Source statement data from the parsed extension instance.
2230 * @param[in] parent Parent node to connect to (not into).
2231 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002232 * @return LY_ERR values.
2233 */
2234static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002235lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002236 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002237{
2238 struct lysp_node_leaflist *llist;
2239
2240 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2241
2242 /* create new leaf-list structure */
2243 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2244 llist->nodetype = LYS_LEAFLIST;
2245 llist->parent = parent;
2246
2247 /* get name */
2248 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2249
2250 /* parse substatements */
2251 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2252 switch (child->kw) {
2253 case LY_STMT_CONFIG:
2254 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2255 break;
2256 case LY_STMT_DEFAULT:
2257 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2258 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2259 break;
2260 case LY_STMT_DESCRIPTION:
2261 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2262 break;
2263 case LY_STMT_IF_FEATURE:
2264 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2265 break;
2266 case LY_STMT_MAX_ELEMENTS:
2267 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2268 break;
2269 case LY_STMT_MIN_ELEMENTS:
2270 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2271 break;
2272 case LY_STMT_MUST:
2273 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2274 break;
2275 case LY_STMT_ORDERED_BY:
2276 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2277 break;
2278 case LY_STMT_REFERENCE:
2279 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2280 break;
2281 case LY_STMT_STATUS:
2282 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2283 break;
2284 case LY_STMT_TYPE:
2285 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2286 break;
2287 case LY_STMT_UNITS:
2288 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2289 break;
2290 case LY_STMT_WHEN:
2291 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2292 break;
2293 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002294 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002295 break;
2296 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002297 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002298 return LY_EVALID;
2299 }
2300 }
2301
2302 /* mandatory substatements */
2303 if (!llist->type.name) {
2304 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2305 return LY_EVALID;
2306 }
2307
2308 return LY_SUCCESS;
2309}
2310
2311/**
2312 * @brief Parse the refine statement.
2313 *
2314 * @param[in] ctx parser context.
2315 * @param[in] stmt Source statement data from the parsed extension instance.
2316 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002317 * @return LY_ERR values.
2318 */
2319static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002320lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002321{
2322 struct lysp_refine *rf;
2323
2324 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2325
2326 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2327
2328 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2329
2330 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2331 switch (child->kw) {
2332 case LY_STMT_CONFIG:
2333 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2334 break;
2335 case LY_STMT_DEFAULT:
2336 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2337 break;
2338 case LY_STMT_DESCRIPTION:
2339 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2340 break;
2341 case LY_STMT_IF_FEATURE:
2342 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2343 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2344 break;
2345 case LY_STMT_MAX_ELEMENTS:
2346 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2347 break;
2348 case LY_STMT_MIN_ELEMENTS:
2349 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2350 break;
2351 case LY_STMT_MUST:
2352 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2353 break;
2354 case LY_STMT_MANDATORY:
2355 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2356 break;
2357 case LY_STMT_REFERENCE:
2358 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2359 break;
2360 case LY_STMT_PRESENCE:
2361 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2362 break;
2363 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002364 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002365 break;
2366 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002367 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002368 return LY_EVALID;
2369 }
2370 }
2371
2372 return LY_SUCCESS;
2373}
2374
2375/**
2376 * @brief Parse the typedef statement.
2377 *
2378 * @param[in] ctx parser context.
2379 * @param[in] stmt Source statement data from the parsed extension instance.
2380 * @param[in] parent Parent node to connect to (not into).
2381 * @param[in,out] typedefs Typedefs to add to.
2382 *
2383 * @return LY_ERR values.
2384 */
2385static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002386lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002387 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002388{
2389 struct lysp_tpdf *tpdf;
2390
2391 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2392
2393 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2394
2395 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2396
2397 /* parse substatements */
2398 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2399 switch (child->kw) {
2400 case LY_STMT_DEFAULT:
2401 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 +01002402 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002403 break;
2404 case LY_STMT_DESCRIPTION:
2405 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2406 break;
2407 case LY_STMT_REFERENCE:
2408 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2409 break;
2410 case LY_STMT_STATUS:
2411 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2412 break;
2413 case LY_STMT_TYPE:
2414 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2415 break;
2416 case LY_STMT_UNITS:
2417 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2418 break;
2419 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002420 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002421 break;
2422 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002423 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002424 return LY_EVALID;
2425 }
2426 }
2427
2428 /* mandatory substatements */
2429 if (!tpdf->type.name) {
2430 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2431 return LY_EVALID;
2432 }
2433
2434 /* store data for collision check */
2435 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2436 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2437 }
2438
2439 return LY_SUCCESS;
2440}
2441
2442/**
2443 * @brief Parse the input or output statement.
2444 *
2445 * @param[in] ctx parser context.
2446 * @param[in] stmt Source statement data from the parsed extension instance.
2447 * @param[in] parent Parent node to connect to (not into).
2448 * @param[in,out] inout_p Input/output pointer to write to.
2449 *
2450 * @return LY_ERR values.
2451 */
2452static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002453lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002454 struct lysp_node_action_inout *inout_p)
2455{
2456 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002457 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002458 return LY_EVALID;
2459 }
2460
2461 /* initiate structure */
2462 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2463 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2464 inout_p->parent = parent;
2465
2466 /* parse substatements */
2467 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2468 switch (child->kw) {
2469 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002470 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002471 /* fall through */
2472 case LY_STMT_ANYXML:
2473 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2474 break;
2475 case LY_STMT_CHOICE:
2476 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2477 break;
2478 case LY_STMT_CONTAINER:
2479 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2480 break;
2481 case LY_STMT_LEAF:
2482 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2483 break;
2484 case LY_STMT_LEAF_LIST:
2485 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2486 break;
2487 case LY_STMT_LIST:
2488 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2489 break;
2490 case LY_STMT_USES:
2491 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2492 break;
2493 case LY_STMT_TYPEDEF:
2494 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2495 break;
2496 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002497 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002498 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2499 break;
2500 case LY_STMT_GROUPING:
2501 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2502 break;
2503 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002504 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002505 break;
2506 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002507 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002508 return LY_EVALID;
2509 }
2510 }
2511
2512 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002513 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002514 return LY_EVALID;
2515 }
2516
2517 return LY_SUCCESS;
2518}
2519
2520/**
2521 * @brief Parse the action statement.
2522 *
2523 * @param[in] ctx parser context.
2524 * @param[in] stmt Source statement data from the parsed extension instance.
2525 * @param[in] parent Parent node to connect to (not into).
2526 * @param[in,out] actions Actions to add to.
2527 *
2528 * @return LY_ERR values.
2529 */
2530static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002531lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002532 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002533{
2534 struct lysp_node_action *act;
2535
2536 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2537
2538 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2539
2540 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2541 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2542 act->parent = parent;
2543
2544 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2545 switch (child->kw) {
2546 case LY_STMT_DESCRIPTION:
2547 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2548 break;
2549 case LY_STMT_IF_FEATURE:
2550 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2551 break;
2552 case LY_STMT_REFERENCE:
2553 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2554 break;
2555 case LY_STMT_STATUS:
2556 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2557 break;
2558
2559 case LY_STMT_INPUT:
2560 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2561 break;
2562 case LY_STMT_OUTPUT:
2563 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2564 break;
2565
2566 case LY_STMT_TYPEDEF:
2567 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2568 break;
2569 case LY_STMT_GROUPING:
2570 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2571 break;
2572 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002573 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 +01002574 break;
2575 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002576 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002577 return LY_EVALID;
2578 }
2579 }
2580
2581 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2582 if (!act->input.nodetype) {
2583 act->input.nodetype = LYS_INPUT;
2584 act->input.parent = &act->node;
2585 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2586 }
2587 if (!act->output.nodetype) {
2588 act->output.nodetype = LYS_OUTPUT;
2589 act->output.parent = &act->node;
2590 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2591 }
2592
2593 return LY_SUCCESS;
2594}
2595
2596/**
2597 * @brief Parse the notification statement.
2598 *
2599 * @param[in] ctx parser context.
2600 * @param[in] stmt Source statement data from the parsed extension instance.
2601 * @param[in] parent Parent node to connect to (not into).
2602 * @param[in,out] notifs Notifications to add to.
2603 *
2604 * @return LY_ERR values.
2605 */
2606static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002607lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002608 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002609{
2610 struct lysp_node_notif *notif;
2611
2612 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2613
2614 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2615
2616 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2617 notif->nodetype = LYS_NOTIF;
2618 notif->parent = parent;
2619
2620 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2621 switch (child->kw) {
2622 case LY_STMT_DESCRIPTION:
2623 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2624 break;
2625 case LY_STMT_IF_FEATURE:
2626 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2627 break;
2628 case LY_STMT_REFERENCE:
2629 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2630 break;
2631 case LY_STMT_STATUS:
2632 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2633 break;
2634
2635 case LY_STMT_ANYDATA:
2636 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2637 /* fall through */
2638 case LY_STMT_ANYXML:
2639 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2640 break;
2641 case LY_STMT_CHOICE:
2642 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2643 break;
2644 case LY_STMT_CONTAINER:
2645 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2646 break;
2647 case LY_STMT_LEAF:
2648 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2649 break;
2650 case LY_STMT_LEAF_LIST:
2651 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2652 break;
2653 case LY_STMT_LIST:
2654 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2655 break;
2656 case LY_STMT_USES:
2657 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2658 break;
2659
2660 case LY_STMT_MUST:
2661 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2662 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2663 break;
2664 case LY_STMT_TYPEDEF:
2665 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2666 break;
2667 case LY_STMT_GROUPING:
2668 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2669 break;
2670 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002671 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002672 break;
2673 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002674 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002675 return LY_EVALID;
2676 }
2677 }
2678
2679 return LY_SUCCESS;
2680}
2681
2682/**
2683 * @brief Parse the grouping statement.
2684 *
2685 * @param[in] ctx parser context.
2686 * @param[in] stmt Source statement data from the parsed extension instance.
2687 * @param[in] parent Parent node to connect to (not into).
2688 * @param[in,out] groupings Groupings to add to.
2689 *
2690 * @return LY_ERR values.
2691 */
2692static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002693lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002694 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002695{
2696 struct lysp_node_grp *grp;
2697
2698 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2699
2700 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2701
2702 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2703 grp->nodetype = LYS_GROUPING;
2704 grp->parent = parent;
2705
2706 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2707 switch (child->kw) {
2708 case LY_STMT_DESCRIPTION:
2709 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2710 break;
2711 case LY_STMT_REFERENCE:
2712 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2713 break;
2714 case LY_STMT_STATUS:
2715 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2716 break;
2717
2718 case LY_STMT_ANYDATA:
2719 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2720 /* fall through */
2721 case LY_STMT_ANYXML:
2722 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2723 break;
2724 case LY_STMT_CHOICE:
2725 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2726 break;
2727 case LY_STMT_CONTAINER:
2728 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2729 break;
2730 case LY_STMT_LEAF:
2731 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2732 break;
2733 case LY_STMT_LEAF_LIST:
2734 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2735 break;
2736 case LY_STMT_LIST:
2737 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2738 break;
2739 case LY_STMT_USES:
2740 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2741 break;
2742
2743 case LY_STMT_TYPEDEF:
2744 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2745 break;
2746 case LY_STMT_ACTION:
2747 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2748 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2749 break;
2750 case LY_STMT_GROUPING:
2751 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2752 break;
2753 case LY_STMT_NOTIFICATION:
2754 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2755 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2756 break;
2757 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002758 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002759 break;
2760 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002761 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002762 return LY_EVALID;
2763 }
2764 }
2765
2766 return LY_SUCCESS;
2767}
2768
2769/**
2770 * @brief Parse the augment statement.
2771 *
2772 * @param[in] ctx parser context.
2773 * @param[in] stmt Source statement data from the parsed extension instance.
2774 * @param[in] parent Parent node to connect to (not into).
2775 * @param[in,out] augments Augments to add to.
2776 *
2777 * @return LY_ERR values.
2778 */
2779static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002780lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002781 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002782{
2783 struct lysp_node_augment *aug;
2784
2785 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2786
2787 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2788
2789 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2790 aug->nodetype = LYS_AUGMENT;
2791 aug->parent = parent;
2792
2793 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2794 switch (child->kw) {
2795 case LY_STMT_DESCRIPTION:
2796 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2797 break;
2798 case LY_STMT_IF_FEATURE:
2799 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2800 break;
2801 case LY_STMT_REFERENCE:
2802 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2803 break;
2804 case LY_STMT_STATUS:
2805 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2806 break;
2807 case LY_STMT_WHEN:
2808 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2809 break;
2810
2811 case LY_STMT_ANYDATA:
2812 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2813 /* fall through */
2814 case LY_STMT_ANYXML:
2815 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2816 break;
2817 case LY_STMT_CASE:
2818 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2819 break;
2820 case LY_STMT_CHOICE:
2821 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2822 break;
2823 case LY_STMT_CONTAINER:
2824 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2825 break;
2826 case LY_STMT_LEAF:
2827 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2828 break;
2829 case LY_STMT_LEAF_LIST:
2830 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2831 break;
2832 case LY_STMT_LIST:
2833 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2834 break;
2835 case LY_STMT_USES:
2836 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2837 break;
2838
2839 case LY_STMT_ACTION:
2840 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2841 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2842 break;
2843 case LY_STMT_NOTIFICATION:
2844 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2845 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2846 break;
2847 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002848 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002849 break;
2850 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002851 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002852 return LY_EVALID;
2853 }
2854 }
2855
2856 return LY_SUCCESS;
2857}
2858
2859/**
2860 * @brief Parse the uses statement.
2861 *
2862 * @param[in] ctx parser context.
2863 * @param[in] stmt Source statement data from the parsed extension instance.
2864 * @param[in] parent Parent node to connect to (not into).
2865 * @param[in,out] siblings Siblings to add to.
2866 *
2867 * @return LY_ERR values.
2868 */
2869static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002870lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002871 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002872{
2873 struct lysp_node_uses *uses;
2874
2875 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2876
2877 /* create uses structure */
2878 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2879
2880 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2881 uses->nodetype = LYS_USES;
2882 uses->parent = parent;
2883
2884 /* parse substatements */
2885 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2886 switch (child->kw) {
2887 case LY_STMT_DESCRIPTION:
2888 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2889 break;
2890 case LY_STMT_IF_FEATURE:
2891 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2892 break;
2893 case LY_STMT_REFERENCE:
2894 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2895 break;
2896 case LY_STMT_STATUS:
2897 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2898 break;
2899 case LY_STMT_WHEN:
2900 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2901 break;
2902
2903 case LY_STMT_REFINE:
2904 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2905 break;
2906 case LY_STMT_AUGMENT:
2907 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2908 break;
2909 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002910 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002911 break;
2912 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002913 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002914 return LY_EVALID;
2915 }
2916 }
2917
2918 return LY_SUCCESS;
2919}
2920
2921/**
2922 * @brief Parse the case statement.
2923 *
2924 * @param[in] ctx parser context.
2925 * @param[in] stmt Source statement data from the parsed extension instance.
2926 * @param[in] parent Parent node to connect to (not into).
2927 * @param[in,out] siblings Siblings to add to.
2928 *
2929 * @return LY_ERR values.
2930 */
2931static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002932lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002933 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002934{
2935 struct lysp_node_case *cas;
2936
2937 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2938
2939 /* create new case structure */
2940 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2941
2942 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2943 cas->nodetype = LYS_CASE;
2944 cas->parent = parent;
2945
2946 /* parse substatements */
2947 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2948 switch (child->kw) {
2949 case LY_STMT_DESCRIPTION:
2950 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2951 break;
2952 case LY_STMT_IF_FEATURE:
2953 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2954 break;
2955 case LY_STMT_REFERENCE:
2956 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2957 break;
2958 case LY_STMT_STATUS:
2959 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2960 break;
2961 case LY_STMT_WHEN:
2962 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2963 break;
2964
2965 case LY_STMT_ANYDATA:
2966 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2967 /* fall through */
2968 case LY_STMT_ANYXML:
2969 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2970 break;
2971 case LY_STMT_CHOICE:
2972 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2973 break;
2974 case LY_STMT_CONTAINER:
2975 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2976 break;
2977 case LY_STMT_LEAF:
2978 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2979 break;
2980 case LY_STMT_LEAF_LIST:
2981 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2982 break;
2983 case LY_STMT_LIST:
2984 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2985 break;
2986 case LY_STMT_USES:
2987 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2988 break;
2989 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002990 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002991 break;
2992 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002993 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002994 return LY_EVALID;
2995 }
2996 }
2997 return LY_SUCCESS;
2998}
2999
3000/**
3001 * @brief Parse the choice statement.
3002 *
3003 * @param[in] ctx parser context.
3004 * @param[in] stmt Source statement data from the parsed extension instance.
3005 * @param[in] parent Parent node to connect to (not into).
3006 * @param[in,out] siblings Siblings to add to.
3007 *
3008 * @return LY_ERR values.
3009 */
3010static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003011lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003012 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003013{
3014 struct lysp_node_choice *choice;
3015
3016 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3017
3018 /* create new choice structure */
3019 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
3020
3021 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
3022 choice->nodetype = LYS_CHOICE;
3023 choice->parent = parent;
3024
3025 /* parse substatements */
3026 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3027 switch (child->kw) {
3028 case LY_STMT_CONFIG:
3029 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
3030 break;
3031 case LY_STMT_DESCRIPTION:
3032 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
3033 break;
3034 case LY_STMT_IF_FEATURE:
3035 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
3036 break;
3037 case LY_STMT_MANDATORY:
3038 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
3039 break;
3040 case LY_STMT_REFERENCE:
3041 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
3042 break;
3043 case LY_STMT_STATUS:
3044 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
3045 break;
3046 case LY_STMT_WHEN:
3047 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
3048 break;
3049 case LY_STMT_DEFAULT:
3050 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 +01003051 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003052 break;
3053 case LY_STMT_ANYDATA:
3054 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
3055 /* fall through */
3056 case LY_STMT_ANYXML:
3057 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
3058 break;
3059 case LY_STMT_CASE:
3060 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
3061 break;
3062 case LY_STMT_CHOICE:
3063 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
3064 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
3065 break;
3066 case LY_STMT_CONTAINER:
3067 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
3068 break;
3069 case LY_STMT_LEAF:
3070 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
3071 break;
3072 case LY_STMT_LEAF_LIST:
3073 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
3074 break;
3075 case LY_STMT_LIST:
3076 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
3077 break;
3078 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003079 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003080 break;
3081 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003082 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003083 return LY_EVALID;
3084 }
3085 }
3086 return LY_SUCCESS;
3087}
3088
3089/**
3090 * @brief Parse the container statement.
3091 *
3092 * @param[in] ctx parser context.
3093 * @param[in] stmt Source statement data from the parsed extension instance.
3094 * @param[in] parent Parent node to connect to (not into).
3095 * @param[in,out] siblings Siblings to add to.
3096 *
3097 * @return LY_ERR values.
3098 */
3099static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003100lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003101 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003102{
3103 struct lysp_node_container *cont;
3104
3105 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3106
3107 /* create new container structure */
3108 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
3109
3110 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
3111 cont->nodetype = LYS_CONTAINER;
3112 cont->parent = parent;
3113
3114 /* parse substatements */
3115 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3116 switch (child->kw) {
3117 case LY_STMT_CONFIG:
3118 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
3119 break;
3120 case LY_STMT_DESCRIPTION:
3121 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
3122 break;
3123 case LY_STMT_IF_FEATURE:
3124 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
3125 break;
3126 case LY_STMT_REFERENCE:
3127 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
3128 break;
3129 case LY_STMT_STATUS:
3130 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
3131 break;
3132 case LY_STMT_WHEN:
3133 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
3134 break;
3135 case LY_STMT_PRESENCE:
3136 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
3137 break;
3138 case LY_STMT_ANYDATA:
3139 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
3140 /* fall through */
3141 case LY_STMT_ANYXML:
3142 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
3143 break;
3144 case LY_STMT_CHOICE:
3145 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
3146 break;
3147 case LY_STMT_CONTAINER:
3148 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
3149 break;
3150 case LY_STMT_LEAF:
3151 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
3152 break;
3153 case LY_STMT_LEAF_LIST:
3154 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
3155 break;
3156 case LY_STMT_LIST:
3157 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
3158 break;
3159 case LY_STMT_USES:
3160 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
3161 break;
3162
3163 case LY_STMT_TYPEDEF:
3164 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
3165 break;
3166 case LY_STMT_MUST:
3167 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
3168 break;
3169 case LY_STMT_ACTION:
3170 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
3171 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
3172 break;
3173 case LY_STMT_GROUPING:
3174 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3175 break;
3176 case LY_STMT_NOTIFICATION:
3177 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3178 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3179 break;
3180 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003181 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003182 break;
3183 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003184 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003185 return LY_EVALID;
3186 }
3187 }
3188
3189 return LY_SUCCESS;
3190}
3191
3192/**
3193 * @brief Parse the list statement.
3194 *
3195 * @param[in] ctx parser context.
3196 * @param[in] stmt Source statement data from the parsed extension instance.
3197 * @param[in] parent Parent node to connect to (not into).
3198 * @param[in,out] siblings Siblings to add to.
3199 *
3200 * @return LY_ERR values.
3201 */
3202static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003203lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003204 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003205{
3206 struct lysp_node_list *list;
3207
3208 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3209
3210 /* create new list structure */
3211 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3212
3213 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3214 list->nodetype = LYS_LIST;
3215 list->parent = parent;
3216
3217 /* parse substatements */
3218 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3219 switch (child->kw) {
3220 case LY_STMT_CONFIG:
3221 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3222 break;
3223 case LY_STMT_DESCRIPTION:
3224 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3225 break;
3226 case LY_STMT_IF_FEATURE:
3227 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3228 break;
3229 case LY_STMT_REFERENCE:
3230 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3231 break;
3232 case LY_STMT_STATUS:
3233 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3234 break;
3235 case LY_STMT_WHEN:
3236 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3237 break;
3238 case LY_STMT_KEY:
3239 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3240 break;
3241 case LY_STMT_MAX_ELEMENTS:
3242 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3243 break;
3244 case LY_STMT_MIN_ELEMENTS:
3245 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3246 break;
3247 case LY_STMT_ORDERED_BY:
3248 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3249 break;
3250 case LY_STMT_UNIQUE:
3251 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3252 break;
3253
3254 case LY_STMT_ANYDATA:
3255 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3256 /* fall through */
3257 case LY_STMT_ANYXML:
3258 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3259 break;
3260 case LY_STMT_CHOICE:
3261 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3262 break;
3263 case LY_STMT_CONTAINER:
3264 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3265 break;
3266 case LY_STMT_LEAF:
3267 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3268 break;
3269 case LY_STMT_LEAF_LIST:
3270 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3271 break;
3272 case LY_STMT_LIST:
3273 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3274 break;
3275 case LY_STMT_USES:
3276 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3277 break;
3278
3279 case LY_STMT_TYPEDEF:
3280 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3281 break;
3282 case LY_STMT_MUST:
3283 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3284 break;
3285 case LY_STMT_ACTION:
3286 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3287 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3288 break;
3289 case LY_STMT_GROUPING:
3290 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3291 break;
3292 case LY_STMT_NOTIFICATION:
3293 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3294 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3295 break;
3296 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003297 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003298 break;
3299 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003300 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003301 return LY_EVALID;
3302 }
3303 }
3304
3305 return LY_SUCCESS;
3306}
3307
Michal Vasko193dacd2022-10-13 08:43:05 +02003308/**
3309 * @brief Parse generic statement structure into a specific parsed-schema structure.
3310 *
3311 * @param[in] pctx Parse context of the @p stmt being processed.
3312 * @param[in] stmt Generic statement structure to process.
3313 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3314 * @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.
3315 * @return LY_ERR value.
3316 */
3317static LY_ERR
3318lysp_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 +02003319{
Radek Krejciad5963b2019-09-06 16:03:05 +02003320 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003321 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003322
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003323 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003324 case LY_STMT_NOTIFICATION:
3325 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3326 break;
3327 case LY_STMT_INPUT:
3328 case LY_STMT_OUTPUT: {
3329 struct lysp_node_action_inout *inout;
3330
3331 *result = inout = calloc(1, sizeof *inout);
3332 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3333 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3334 break;
3335 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003336 case LY_STMT_ACTION:
3337 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003338 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003339 break;
3340 case LY_STMT_ANYDATA:
3341 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003342 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003343 break;
3344 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003345 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003346 break;
3347 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003348 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003349 break;
3350 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003351 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003352 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003353 case LY_STMT_CONTAINER:
3354 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003355 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003356 case LY_STMT_GROUPING:
3357 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3358 break;
3359 case LY_STMT_LEAF:
3360 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3361 break;
3362 case LY_STMT_LEAF_LIST:
3363 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3364 break;
3365 case LY_STMT_LIST:
3366 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3367 break;
3368 case LY_STMT_USES:
3369 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3370 break;
3371 case LY_STMT_BASE:
3372 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3373 break;
3374 case LY_STMT_ARGUMENT:
3375 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003376 case LY_STMT_CONTACT:
3377 case LY_STMT_DESCRIPTION:
3378 case LY_STMT_ERROR_APP_TAG:
3379 case LY_STMT_ERROR_MESSAGE:
3380 case LY_STMT_KEY:
3381 case LY_STMT_NAMESPACE:
3382 case LY_STMT_ORGANIZATION:
3383 case LY_STMT_PRESENCE:
3384 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003385 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003386 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003387 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003388 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003389 case LY_STMT_BIT:
3390 case LY_STMT_ENUM:
3391 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3392 break;
3393 case LY_STMT_CONFIG:
3394 assert(*result);
3395 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003396 break;
3397 case LY_STMT_DEFAULT:
3398 case LY_STMT_IF_FEATURE:
3399 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003400 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3401 break;
3402 case LY_STMT_DEVIATE:
3403 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3404 break;
3405 case LY_STMT_DEVIATION:
3406 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3407 break;
3408 case LY_STMT_EXTENSION:
3409 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003410 break;
3411 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003412 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3413 break;
3414 case LY_STMT_FEATURE:
3415 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003416 break;
3417 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003418 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003419 break;
3420 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003421 case LY_STMT_RANGE: {
3422 struct lysp_restr *restr;
3423
3424 *result = restr = calloc(1, sizeof *restr);
3425 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3426
3427 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003428 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003429 }
3430 case LY_STMT_MUST:
3431 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3432 break;
3433 case LY_STMT_IDENTITY:
3434 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3435 break;
3436 case LY_STMT_IMPORT:
3437 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3438 break;
3439 case LY_STMT_INCLUDE:
3440 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003441 break;
3442 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003443 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003444 break;
3445 case LY_STMT_MAX_ELEMENTS:
3446 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003447 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003448 break;
3449 case LY_STMT_MIN_ELEMENTS:
3450 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003451 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003452 break;
3453 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003454 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003455 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003456 case LY_STMT_MODULE: {
3457 struct lysp_module *mod;
3458
3459 *result = mod = calloc(1, sizeof *mod);
3460 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3461 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003462 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003463 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003464 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003465 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003466 break;
3467 case LY_STMT_PATH: {
3468 const char *str_path = NULL;
3469
Michal Vasko193dacd2022-10-13 08:43:05 +02003470 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3471 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003472 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003473 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003474 break;
3475 }
3476 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003477 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003478 break;
3479 case LY_STMT_POSITION:
3480 case LY_STMT_VALUE:
3481 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003482 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003483 break;
3484 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003485 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003486 break;
3487 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003488 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003489 break;
3490 case LY_STMT_REQUIRE_INSTANCE:
3491 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003492 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3493 break;
3494 case LY_STMT_REVISION:
3495 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003496 break;
Michal Vasko69730152020-10-09 16:30:07 +02003497 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003498 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003499 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003500 case LY_STMT_SUBMODULE: {
3501 struct lysp_submodule *submod;
3502
3503 *result = submod = calloc(1, sizeof *submod);
3504 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3505 ret = lysp_stmt_submodule(pctx, stmt, submod);
3506 break;
3507 }
Radek Krejci335332a2019-09-05 13:03:35 +02003508 case LY_STMT_TYPE: {
3509 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003510
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003511 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003512 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3513 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003514 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003515 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003516 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003517 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003518 break;
3519 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003520 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3521 break;
3522 case LY_STMT_YANG_VERSION:
3523 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3524 break;
3525 case LY_STMT_YIN_ELEMENT:
3526 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003527 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003528 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003529 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003530 return LY_EINT;
3531 }
3532
Radek Krejciad5963b2019-09-06 16:03:05 +02003533 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003534}
Michal Vasko59892dd2022-05-13 11:02:30 +02003535
Michal Vasko193dacd2022-10-13 08:43:05 +02003536LY_ERR
3537lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003538{
Michal Vasko193dacd2022-10-13 08:43:05 +02003539 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003540
Michal Vasko193dacd2022-10-13 08:43:05 +02003541 if (!substmt->storage) {
3542 /* nothing to parse, ignored */
3543 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003544 }
3545
Michal Vasko193dacd2022-10-13 08:43:05 +02003546 switch (stmt->kw) {
3547 case LY_STMT_NOTIFICATION:
3548 case LY_STMT_INPUT:
3549 case LY_STMT_OUTPUT:
3550 case LY_STMT_ACTION:
3551 case LY_STMT_RPC:
3552 case LY_STMT_ANYDATA:
3553 case LY_STMT_ANYXML:
3554 case LY_STMT_AUGMENT:
3555 case LY_STMT_CASE:
3556 case LY_STMT_CHOICE:
3557 case LY_STMT_CONTAINER:
3558 case LY_STMT_GROUPING:
3559 case LY_STMT_LEAF:
3560 case LY_STMT_LEAF_LIST:
3561 case LY_STMT_LIST:
3562 case LY_STMT_USES: {
3563 struct lysp_node **pnodes_p, *pnode = NULL;
3564
3565 /* parse the node */
3566 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3567
3568 /* usually is a linked-list of all the parsed schema nodes */
3569 pnodes_p = substmt->storage;
3570 while (*pnodes_p) {
3571 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003572 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003573 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003574
3575 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003576 }
3577 case LY_STMT_BASE:
3578 case LY_STMT_BIT:
3579 case LY_STMT_DEFAULT:
3580 case LY_STMT_DEVIATE:
3581 case LY_STMT_DEVIATION:
3582 case LY_STMT_ENUM:
3583 case LY_STMT_EXTENSION:
3584 case LY_STMT_EXTENSION_INSTANCE:
3585 case LY_STMT_FEATURE:
3586 case LY_STMT_IDENTITY:
3587 case LY_STMT_IF_FEATURE:
3588 case LY_STMT_IMPORT:
3589 case LY_STMT_INCLUDE:
3590 case LY_STMT_MUST:
3591 case LY_STMT_PATTERN:
3592 case LY_STMT_REFINE:
3593 case LY_STMT_REVISION:
3594 case LY_STMT_TYPEDEF:
3595 case LY_STMT_UNIQUE:
3596 /* parse, sized array */
3597 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003598 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003599
3600 case LY_STMT_ARGUMENT:
3601 case LY_STMT_BELONGS_TO:
3602 case LY_STMT_CONTACT:
3603 case LY_STMT_DESCRIPTION:
3604 case LY_STMT_ERROR_APP_TAG:
3605 case LY_STMT_ERROR_MESSAGE:
3606 case LY_STMT_FRACTION_DIGITS:
3607 case LY_STMT_KEY:
3608 case LY_STMT_LENGTH:
3609 case LY_STMT_MANDATORY:
3610 case LY_STMT_MAX_ELEMENTS:
3611 case LY_STMT_MIN_ELEMENTS:
3612 case LY_STMT_MODIFIER:
3613 case LY_STMT_MODULE:
3614 case LY_STMT_NAMESPACE:
3615 case LY_STMT_ORGANIZATION:
3616 case LY_STMT_PATH:
3617 case LY_STMT_POSITION:
3618 case LY_STMT_PREFIX:
3619 case LY_STMT_PRESENCE:
3620 case LY_STMT_RANGE:
3621 case LY_STMT_REFERENCE:
3622 case LY_STMT_REQUIRE_INSTANCE:
3623 case LY_STMT_REVISION_DATE:
3624 case LY_STMT_SUBMODULE:
3625 case LY_STMT_TYPE:
3626 case LY_STMT_UNITS:
3627 case LY_STMT_VALUE:
3628 case LY_STMT_WHEN:
3629 case LY_STMT_YANG_VERSION:
3630 case LY_STMT_YIN_ELEMENT:
3631 /* single item */
3632 if (*(void **)substmt->storage) {
3633 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3634 rc = LY_EVALID;
3635 goto cleanup;
3636 }
3637
3638 /* parse */
3639 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003640 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003641
3642 case LY_STMT_CONFIG:
3643 /* single item */
3644 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3645 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3646 rc = LY_EVALID;
3647 goto cleanup;
3648 }
3649
3650 /* parse */
3651 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3652 break;
3653
3654 case LY_STMT_ORDERED_BY:
3655 /* single item */
3656 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3657 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3658 rc = LY_EVALID;
3659 goto cleanup;
3660 }
3661
3662 /* parse */
3663 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3664 break;
3665
3666 case LY_STMT_STATUS:
3667 /* single item */
3668 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3669 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3670 rc = LY_EVALID;
3671 goto cleanup;
3672 }
3673
3674 /* parse */
3675 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3676 break;
3677
Michal Vasko59892dd2022-05-13 11:02:30 +02003678 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003679 LOGINT(PARSER_CTX(pctx));
3680 rc = LY_EINT;
3681 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003682 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003683
3684cleanup:
3685 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003686}