blob: 693ca656bc9e645ec0ad65387625291b99984473 [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
160LY_ERR
161lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
162{
163 LY_ERR rc = LY_SUCCESS;
164
165 LOG_LOCSET(snode, NULL, NULL, NULL);
166
167 if (lydctx->int_opts & LYD_INTOPT_ANY) {
168 /* nothing to check, everything is allowed */
169 goto cleanup;
170 }
171
172 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
173 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
174 rc = LY_EVALID;
175 goto cleanup;
176 }
177
178 if (snode->nodetype == LYS_RPC) {
179 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
180 if (lydctx->op_node) {
181 goto error_node_dup;
182 }
183 } else {
184 goto error_node_inval;
185 }
186 } else if (snode->nodetype == LYS_ACTION) {
187 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
188 if (lydctx->op_node) {
189 goto error_node_dup;
190 }
191 } else {
192 goto error_node_inval;
193 }
194 } else if (snode->nodetype == LYS_NOTIF) {
195 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
196 if (lydctx->op_node) {
197 goto error_node_dup;
198 }
199 } else {
200 goto error_node_inval;
201 }
202 }
203
204 /* success */
205 goto cleanup;
206
207error_node_dup:
208 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
209 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
210 lydctx->op_node->schema->name);
211 rc = LY_EVALID;
212 goto cleanup;
213
214error_node_inval:
215 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
216 snode->name);
217 rc = LY_EVALID;
218
219cleanup:
220 LOG_LOCBACK(1, 0, 0, 0);
221 return rc;
222}
223
224LY_ERR
225lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
226 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
227{
Michal Vasko9dbb91d2023-01-30 13:59:22 +0100228 LY_ERR r;
Michal Vasko59892dd2022-05-13 11:02:30 +0200229 ly_bool incomplete;
230
Michal Vasko9dbb91d2023-01-30 13:59:22 +0100231 if ((r = lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node))) {
232 if (lydctx->data_ctx->ctx != schema->module->ctx) {
233 /* move errors to the main context */
234 ly_err_move(schema->module->ctx, (struct ly_ctx *)lydctx->data_ctx->ctx);
235 }
236 return r;
237 }
Michal Vasko59892dd2022-05-13 11:02:30 +0200238
239 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
240 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
241 }
242 return LY_SUCCESS;
243}
244
245LY_ERR
246lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
247 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
248 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
249{
250 ly_bool incomplete;
251 struct lyd_meta *first = NULL;
252
253 if (meta && *meta) {
254 /* remember the first metadata */
255 first = *meta;
256 }
257
258 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
259 hints, ctx_node, 0, &incomplete));
260
261 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
262 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
263 }
264
265 if (first) {
266 /* always return the first metadata */
267 *meta = first;
268 }
269
270 return LY_SUCCESS;
271}
272
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200273LY_ERR
274lyd_parse_check_keys(struct lyd_node *node)
275{
276 const struct lysc_node *skey = NULL;
277 const struct lyd_node *key;
278
279 assert(node->schema->nodetype == LYS_LIST);
280
281 key = lyd_child(node);
282 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
283 if (!key || (key->schema != skey)) {
284 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
285 return LY_EVALID;
286 }
287
288 key = key->next;
289 }
290
291 return LY_SUCCESS;
292}
293
294LY_ERR
295lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
296 struct lysc_ext_instance *ext)
297{
298 struct lyd_meta *meta2, *prev_meta = NULL;
299 struct lyd_ctx_ext_val *ext_val;
300
Michal Vaskobc9f76f2022-12-01 10:31:38 +0100301 if (lydctx->parse_opts & LYD_PARSE_NO_NEW) {
302 node->flags &= ~LYD_NEW;
303 }
304
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200305 if (lysc_has_when(node->schema)) {
Michal Vaskofbb48c22022-11-30 13:28:03 +0100306 if (lydctx->parse_opts & LYD_PARSE_WHEN_TRUE) {
307 /* the condition was true before */
308 node->flags |= LYD_WHEN_TRUE;
309 }
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200310 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
311 /* remember we need to evaluate this node's when */
312 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
313 }
314 }
315
316 LY_LIST_FOR(*meta, meta2) {
317 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
318 meta2->value.boolean) {
319 /* node is default according to the metadata */
320 node->flags |= LYD_DEFAULT;
321
322 /* delete the metadata */
323 if (prev_meta) {
324 prev_meta->next = meta2->next;
Michal Vasko4754d4a2022-12-01 10:11:21 +0100325 } else if (meta != &node->meta) {
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200326 *meta = (*meta)->next;
327 }
328 lyd_free_meta_single(meta2);
Michal Vasko4754d4a2022-12-01 10:11:21 +0100329
330 /* update dflt flag for all parent NP containers */
331 lyd_cont_set_dflt(lyd_parent(node));
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200332 break;
333 }
334
335 prev_meta = meta2;
336 }
337
338 if (ext) {
339 /* parsed for an extension */
340 node->flags |= LYD_EXT;
341
342 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
343 /* rememeber for validation */
344 ext_val = malloc(sizeof *ext_val);
345 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
346 ext_val->ext = ext;
347 ext_val->sibling = node;
348 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
349 }
350 }
351
352 return LY_SUCCESS;
353}
354
Michal Vasko193dacd2022-10-13 08:43:05 +0200355void
356lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
357{
358 char path[PATH_MAX];
359
360#ifndef __APPLE__
361 char proc_path[32];
362 int len;
363#endif
364
365 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
366 if (*filepath) {
367 /* filepath already set */
368 return;
369 }
370
371 switch (in->type) {
372 case LY_IN_FILEPATH:
373 if (realpath(in->method.fpath.filepath, path) != NULL) {
374 lydict_insert(ctx, path, 0, filepath);
375 } else {
376 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
377 }
378
379 break;
380 case LY_IN_FD:
381#ifdef __APPLE__
382 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
383 lydict_insert(ctx, path, 0, filepath);
384 }
385#elif defined _WIN32
386 HANDLE h = _get_osfhandle(in->method.fd);
387 FILE_NAME_INFO info;
Michal Vasko2bf4af42023-01-04 12:08:38 +0100388
Michal Vasko193dacd2022-10-13 08:43:05 +0200389 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
390 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
Michal Vasko2bf4af42023-01-04 12:08:38 +0100391
Michal Vasko193dacd2022-10-13 08:43:05 +0200392 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
393 lydict_insert(ctx, buf, len, filepath);
394 }
395#else
396 /* get URI if there is /proc */
397 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
398 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
399 lydict_insert(ctx, path, len, filepath);
400 }
401#endif
402 break;
403 case LY_IN_MEMORY:
404 case LY_IN_FILE:
405 /* nothing to do */
406 break;
407 default:
408 LOGINT(ctx);
409 break;
410 }
411}
412
Michal Vaskod0625d72022-10-06 15:02:50 +0200413static 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 +0100414 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200415static 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 +0100416 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200417static 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 +0100418 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200419static 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 +0100420 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200421static 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 +0100422 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200423static 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 +0100424 struct lysp_node **siblings);
425
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100426/**
427 * @brief Validate stmt string value.
428 *
429 * @param[in] ctx Parser context.
430 * @param[in] val_type String value type.
431 * @param[in] val Value to validate.
432 * @return LY_ERR value.
433 */
Radek Krejci335332a2019-09-05 13:03:35 +0200434static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200435lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200436{
Radek Krejci857189e2020-09-01 13:26:36 +0200437 uint8_t prefix = 0;
438 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200439 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200440 size_t utf8_char_len;
441
Michal Vaskocfa1a962023-02-27 09:28:45 +0100442 if (!val) {
443 if (val_type == Y_MAYBE_STR_ARG) {
444 /* fine */
445 return LY_SUCCESS;
446 }
447
448 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Missing an expected string.");
449 return LY_EVALID;
450 }
451
Radek Krejci335332a2019-09-05 13:03:35 +0200452 while (*val) {
453 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200454 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200455
456 switch (val_type) {
457 case Y_IDENTIF_ARG:
458 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
459 break;
460 case Y_PREF_IDENTIF_ARG:
461 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
462 break;
463 case Y_STR_ARG:
464 case Y_MAYBE_STR_ARG:
465 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
466 break;
467 }
468 first = 0;
469 }
470
471 return LY_SUCCESS;
472}
473
474/**
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100475 * @brief Duplicate statement siblings, recursively.
476 *
477 * @param[in] ctx Parser context.
478 * @param[in] stmt Statement to duplicate.
479 * @param[out] first First duplicated statement, the rest follow.
480 * @return LY_ERR value.
481 */
482static LY_ERR
483lysp_stmt_dup(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_stmt **first)
484{
485 struct lysp_stmt *child, *last = NULL;
486
487 LY_LIST_FOR(stmt, stmt) {
488 child = calloc(1, sizeof *child);
489 LY_CHECK_ERR_RET(!child, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
490
491 if (last) {
492 last->next = child;
493 } else {
494 assert(!*first);
495 *first = child;
496 }
497 last = child;
498
499 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &child->stmt));
500 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &child->arg));
501 child->format = stmt->format;
502 LY_CHECK_RET(ly_dup_prefix_data(PARSER_CTX(ctx), stmt->format, stmt->prefix_data, &child->prefix_data));
503 child->flags = stmt->flags;
504 child->kw = stmt->kw;
505
506 /* recursively */
507 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &child->child));
508 }
509
510 return LY_SUCCESS;
511}
512
513/**
Radek Krejci335332a2019-09-05 13:03:35 +0200514 * @brief Parse extension instance.
515 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100516 * @param[in] ctx parser context.
517 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100518 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200519 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
520 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200521 * @return LY_ERR values.
522 */
523static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200524lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200525 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200526{
527 struct lysp_ext_instance *e;
528
Michal Vaskob36053d2020-03-26 15:49:30 +0100529 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200530
531 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200532 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100533 e->parent_stmt = insubstmt;
534 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200535 e->parsed = NULL;
Michal Vasko5d10b9b2022-12-14 12:14:20 +0100536 LY_CHECK_RET(lysp_stmt_dup(ctx, stmt->child, &e->child));
Radek Krejci335332a2019-09-05 13:03:35 +0200537
538 /* get optional argument */
539 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200540 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200541 }
542
543 return LY_SUCCESS;
544}
545
546/**
547 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
548 * description, etc...
549 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100550 * @param[in] ctx parser context.
551 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200552 * @param[in] substmt_index Index of this substatement.
553 * @param[in,out] value Place to store the parsed value.
554 * @param[in] arg Type of the YANG keyword argument (of the value).
555 * @param[in,out] exts Extension instances to add to.
556 *
557 * @return LY_ERR values.
558 */
559static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200560lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index, const char **value,
561 enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200562{
Radek Krejci335332a2019-09-05 13:03:35 +0200563 if (*value) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200564 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200565 return LY_EVALID;
566 }
567
568 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200569 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200570
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100571 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
572 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200573 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100574 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200575 break;
576 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200577 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200578 return LY_EVALID;
579 }
580 }
581 return LY_SUCCESS;
582}
583
584/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200585 * @brief Parse a qname that can have more instances such as if-feature.
586 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100587 * @param[in] ctx parser context.
588 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200589 * @param[in,out] qnames Parsed qnames to add to.
590 * @param[in] arg Type of the expected argument.
591 * @param[in,out] exts Extension instances to add to.
592 *
593 * @return LY_ERR values.
594 */
595static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200596lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_qname **qnames, enum yang_arg arg,
597 struct lysp_ext_instance **exts)
Michal Vasko7f45cf22020-10-01 12:49:44 +0200598{
599 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200600
601 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
602
603 /* allocate new pointer */
604 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
605 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100606 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200607
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100608 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
609 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200610 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100611 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200612 break;
613 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200614 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200615 return LY_EVALID;
616 }
617 }
618 return LY_SUCCESS;
619}
620
621/**
Radek Krejci335332a2019-09-05 13:03:35 +0200622 * @brief Parse a generic text field that can have more instances such as base.
623 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100624 * @param[in] ctx parser context.
625 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200626 * @param[in,out] texts Parsed values to add to.
627 * @param[in] arg Type of the expected argument.
628 * @param[in,out] exts Extension instances to add to.
629 *
630 * @return LY_ERR values.
631 */
632static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200633lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char ***texts, enum yang_arg arg,
634 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200635{
636 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200637
638 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
639
640 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100641 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200642 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200643
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100644 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
645 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200646 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100647 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200648 break;
649 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200650 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200651 return LY_EVALID;
652 }
653 }
654 return LY_SUCCESS;
655}
656
657/**
658 * @brief Parse the status statement.
659 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100660 * @param[in] ctx parser context.
661 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200662 * @param[in,out] flags Flags to add to.
663 * @param[in,out] exts Extension instances to add to.
664 *
665 * @return LY_ERR values.
666 */
667static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200668lysp_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 +0200669{
670 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200671
672 if (*flags & LYS_STATUS_MASK) {
673 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
674 return LY_EVALID;
675 }
676
677 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
678 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100679 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200680 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100681 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200682 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100683 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200684 *flags |= LYS_STATUS_OBSLT;
685 } else {
686 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
687 return LY_EVALID;
688 }
689
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100690 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
691 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200692 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100693 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200694 break;
695 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200696 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200697 return LY_EVALID;
698 }
699 }
700 return LY_SUCCESS;
701}
702
703/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100704 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200705 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100706 * @param[in] ctx parser context.
707 * @param[in] stmt Source statement data from the parsed extension instance.
708 * @param[in,out] when_p When pointer to parse to.
709 *
710 * @return LY_ERR values.
711 */
712static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200713lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100714{
715 LY_ERR ret = LY_SUCCESS;
716 struct lysp_when *when;
717
718 if (*when_p) {
719 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
720 return LY_EVALID;
721 }
722
723 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
724
725 when = calloc(1, sizeof *when);
726 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
727 *when_p = when;
728
729 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
730
731 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
732 switch (child->kw) {
733 case LY_STMT_DESCRIPTION:
734 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
735 break;
736 case LY_STMT_REFERENCE:
737 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
738 break;
739 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100740 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100741 break;
742 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200743 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "when");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100744 return LY_EVALID;
745 }
746 }
747 return ret;
748}
749
750/**
751 * @brief Parse the config statement.
752 *
753 * @param[in] ctx parser context.
754 * @param[in] stmt Source statement data from the parsed extension instance.
755 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200756 * @param[in,out] exts Extension instances to add to.
757 *
758 * @return LY_ERR values.
759 */
760static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200761lysp_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 +0200762{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100763 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200764
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100765 if (*flags & LYS_CONFIG_MASK) {
766 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
767 return LY_EVALID;
768 }
769
770 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
771 arg_len = strlen(stmt->arg);
772 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
773 *flags |= LYS_CONFIG_W;
774 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
775 *flags |= LYS_CONFIG_R;
776 } else {
777 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
778 return LY_EVALID;
779 }
780
781 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
782 switch (child->kw) {
783 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100784 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100785 break;
786 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200787 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "config");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100788 return LY_EVALID;
789 }
790 }
791
792 return LY_SUCCESS;
793}
794
795/**
796 * @brief Parse the mandatory statement.
797 *
798 * @param[in] ctx parser context.
799 * @param[in] stmt Source statement data from the parsed extension instance.
800 * @param[in,out] flags Flags to add to.
801 * @param[in,out] exts Extension instances to add to.
802 *
803 * @return LY_ERR values.
804 */
805static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200806lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200807 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100808{
809 size_t arg_len;
810
811 if (*flags & LYS_MAND_MASK) {
812 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
813 return LY_EVALID;
814 }
815
816 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
817 arg_len = strlen(stmt->arg);
818 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
819 *flags |= LYS_MAND_TRUE;
820 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
821 *flags |= LYS_MAND_FALSE;
822 } else {
823 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
824 return LY_EVALID;
825 }
826
827 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
828 switch (child->kw) {
829 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100830 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100831 break;
832 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200833 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "mandatory");
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100834 return LY_EVALID;
835 }
836 }
837
838 return LY_SUCCESS;
839}
840
841/**
842 * @brief Parse a restriction such as range or length.
843 *
844 * @param[in] ctx parser context.
845 * @param[in] stmt Source statement data from the parsed extension instance.
846 * @param[in,out] exts Extension instances to add to.
847 *
848 * @return LY_ERR values.
849 */
850static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200851lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100852{
Radek Krejci335332a2019-09-05 13:03:35 +0200853 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200854 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100855 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200856
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100857 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
858 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200859 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100860 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200861 break;
862 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100863 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200864 break;
865 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100866 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200867 break;
868 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100869 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200870 break;
871 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100872 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200873 break;
874 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200875 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200876 return LY_EVALID;
877 }
878 }
879 return LY_SUCCESS;
880}
881
882/**
883 * @brief Parse a restriction that can have more instances such as must.
884 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100885 * @param[in] ctx parser context.
886 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200887 * @param[in,out] restrs Restrictions to add to.
888 *
889 * @return LY_ERR values.
890 */
891static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200892lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200893{
894 struct lysp_restr *restr;
895
Michal Vaskob36053d2020-03-26 15:49:30 +0100896 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100897 return lysp_stmt_restr(ctx, stmt, restr);
898}
899
900/**
901 * @brief Parse the anydata or anyxml statement.
902 *
903 * @param[in] ctx parser context.
904 * @param[in] stmt Source statement data from the parsed extension instance.
905 * @param[in,out] siblings Siblings to add to.
906 *
907 * @return LY_ERR values.
908 */
909static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200910lysp_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 +0100911{
912 struct lysp_node_anydata *any;
913
914 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
915
916 /* create new structure and insert into siblings */
917 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
918
919 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
920 any->parent = parent;
921
922 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
923
924 /* parse substatements */
925 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
926 switch (child->kw) {
927 case LY_STMT_CONFIG:
928 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
929 break;
930 case LY_STMT_DESCRIPTION:
931 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
932 break;
933 case LY_STMT_IF_FEATURE:
934 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
935 break;
936 case LY_STMT_MANDATORY:
937 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
938 break;
939 case LY_STMT_MUST:
940 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
941 break;
942 case LY_STMT_REFERENCE:
943 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
944 break;
945 case LY_STMT_STATUS:
946 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
947 break;
948 case LY_STMT_WHEN:
949 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
950 break;
951 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100952 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100953 break;
954 default:
Michal Vasko193dacd2022-10-13 08:43:05 +0200955 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
956 (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 +0100957 return LY_EVALID;
958 }
959 }
960
961 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200962}
963
964/**
965 * @brief Parse the value or position statement. Substatement of type enum statement.
966 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100967 * @param[in] ctx parser context.
968 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200969 * @param[in,out] value Value to write to.
970 * @param[in,out] flags Flags to write to.
971 * @param[in,out] exts Extension instances to add to.
972 *
973 * @return LY_ERR values.
974 */
975static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200976lysp_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 +0200977 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200978{
979 size_t arg_len;
980 char *ptr = NULL;
Michal Vasko2bf4af42023-01-04 12:08:38 +0100981 long long num = 0;
982 unsigned long long unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200983
984 if (*flags & LYS_SET_VALUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200985 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200986 return LY_EVALID;
987 }
988 *flags |= LYS_SET_VALUE;
989
990 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
991
992 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100993 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
994 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200995 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200996 goto error;
997 }
998
999 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001000 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001001 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001002 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001003 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001004 goto error;
1005 }
1006 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001007 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001008 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001009 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001010 goto error;
1011 }
1012 }
1013 /* we have not parsed the whole argument */
1014 if ((size_t)(ptr - stmt->arg) != arg_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001015 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001016 goto error;
1017 }
1018 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001019 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001020 goto error;
1021 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001022 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +02001023 *value = num;
1024 } else {
1025 *value = unum;
1026 }
1027
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001028 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1029 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001030 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001031 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 +02001032 break;
1033 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001034 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001035 return LY_EVALID;
1036 }
1037 }
1038 return LY_SUCCESS;
1039
1040error:
1041 return LY_EVALID;
1042}
1043
1044/**
1045 * @brief Parse the enum or bit statement. Substatement of type statement.
1046 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001047 * @param[in] ctx parser context.
1048 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001049 * @param[in,out] enums Enums or bits to add to.
1050 *
1051 * @return LY_ERR values.
1052 */
1053static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001054lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +02001055{
1056 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +02001057
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001058 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 +02001059
Michal Vaskob36053d2020-03-26 15:49:30 +01001060 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001061
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001062 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +02001063 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
1064 } /* else nothing specific for YANG_BIT */
1065
Radek Krejci011e4aa2020-09-04 15:22:31 +02001066 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Michal Vasko193dacd2022-10-13 08:43:05 +02001067 CHECK_UNIQUENESS(ctx, *enums, name, lyplg_ext_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +02001068
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001069 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1070 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001071 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001072 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001073 break;
1074 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001075 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001076 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001077 break;
1078 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001079 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001080 break;
1081 case LY_STMT_STATUS:
1082 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
1083 break;
1084 case LY_STMT_VALUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02001085 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1086 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001087 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001088 break;
1089 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +02001090 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw),
1091 lyplg_ext_stmt2str(stmt->kw)), LY_EVALID);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001092 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001093 break;
1094 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001095 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001096 break;
1097 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001098 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001099 return LY_EVALID;
1100 }
1101 }
Michal Vasko193dacd2022-10-13 08:43:05 +02001102
Radek Krejci335332a2019-09-05 13:03:35 +02001103 return LY_SUCCESS;
1104}
1105
1106/**
1107 * @brief Parse the fraction-digits statement. Substatement of type statement.
1108 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001109 * @param[in] ctx parser context.
1110 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001111 * @param[in,out] fracdig Value to write to.
1112 * @param[in,out] exts Extension instances to add to.
1113 *
1114 * @return LY_ERR values.
1115 */
1116static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001117lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +02001118 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001119{
1120 char *ptr;
1121 size_t arg_len;
Michal Vasko2bf4af42023-01-04 12:08:38 +01001122 unsigned long long num;
Radek Krejci335332a2019-09-05 13:03:35 +02001123
1124 if (*fracdig) {
1125 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
1126 return LY_EVALID;
1127 }
1128
1129 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1130 arg_len = strlen(stmt->arg);
1131 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
1132 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1133 return LY_EVALID;
1134 }
1135
1136 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001137 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +02001138 /* we have not parsed the whole argument */
1139 if ((size_t)(ptr - stmt->arg) != arg_len) {
1140 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
1141 return LY_EVALID;
1142 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001143 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001144 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
1145 return LY_EVALID;
1146 }
1147 *fracdig = num;
1148
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001149 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1150 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001151 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001152 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, 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), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +02001156 return LY_EVALID;
1157 }
1158 }
1159 return LY_SUCCESS;
1160}
1161
1162/**
1163 * @brief Parse the require-instance statement. Substatement of type statement.
1164 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001165 * @param[in] ctx parser context.
1166 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001167 * @param[in,out] reqinst Value to write to.
1168 * @param[in,out] flags Flags 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_reqinstance(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *reqinst, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +02001175 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001176{
1177 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001178
1179 if (*flags & LYS_SET_REQINST) {
1180 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
1181 return LY_EVALID;
1182 }
1183 *flags |= LYS_SET_REQINST;
1184
1185 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1186 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001187 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001188 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001189 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001190 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1191 return LY_EVALID;
1192 }
1193
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001194 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1195 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001196 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001197 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001198 break;
1199 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001200 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001201 return LY_EVALID;
1202 }
1203 }
1204 return LY_SUCCESS;
1205}
1206
1207/**
1208 * @brief Parse the modifier statement. Substatement of type pattern statement.
1209 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001210 * @param[in] ctx parser context.
1211 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001212 * @param[in,out] pat Value to write to.
1213 * @param[in,out] exts Extension instances to add to.
Radek Krejci335332a2019-09-05 13:03:35 +02001214 * @return LY_ERR values.
1215 */
1216static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001217lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001218 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001219{
1220 size_t arg_len;
1221 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001222
Radek Krejcif13b87b2020-12-01 22:02:17 +01001223 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001224 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1225 return LY_EVALID;
1226 }
1227
1228 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1229 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001230 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001231 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1232 return LY_EVALID;
1233 }
1234
1235 /* replace the value in the dictionary */
1236 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001237 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001238 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001239 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001240
Radek Krejcif13b87b2020-12-01 22:02:17 +01001241 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1242 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001243 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001244
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001245 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1246 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001247 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001248 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001249 break;
1250 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001251 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001252 return LY_EVALID;
1253 }
1254 }
1255 return LY_SUCCESS;
1256}
1257
1258/**
1259 * @brief Parse the pattern statement. Substatement of type statement.
1260 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001261 * @param[in] ctx parser context.
1262 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001263 * @param[in,out] patterns Restrictions to add to.
1264 *
1265 * @return LY_ERR values.
1266 */
1267static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001268lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001269{
1270 char *buf;
1271 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001272 struct lysp_restr *restr;
1273
1274 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001275 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001276 arg_len = strlen(stmt->arg);
1277
1278 /* add special meaning first byte */
1279 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001280 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001281 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001282 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001283 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001284 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001285 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001286
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001287 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1288 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001289 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001290 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001291 break;
1292 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001293 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001294 break;
1295 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001296 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001297 break;
1298 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001299 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001300 break;
1301 case LY_STMT_MODIFIER:
1302 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001303 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001304 break;
1305 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001306 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001307 break;
1308 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001309 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001310 return LY_EVALID;
1311 }
1312 }
1313 return LY_SUCCESS;
1314}
1315
1316/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001317 * @brief Parse the deviate statement. Substatement of deviation statement.
1318 *
1319 * @param[in] ctx parser context.
1320 * @param[in] stmt Source statement data from the parsed extension instance.
1321 * @param[in,out] devs Array of deviates to add to.
1322 * @param[in,out] exts Extension instances to add to.
1323 * @return LY_ERR values.
1324 */
1325static LY_ERR
1326lysp_stmt_deviate(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviate **devs, struct lysp_ext_instance **exts)
1327{
1328 (void)stmt;
1329 (void)devs;
1330 (void)exts;
1331
1332 /* TODO */
1333 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"deviate\" substatement is not supported.");
1334 return LY_EINVAL;
1335}
1336
1337/**
1338 * @brief Parse the deviation statement.
1339 *
1340 * @param[in] ctx parser context.
1341 * @param[in] stmt Source statement data from the parsed extension instance.
1342 * @param[in,out] deviations Array of deviations to add to.
1343 * @return LY_ERR values.
1344 */
1345static LY_ERR
1346lysp_stmt_deviation(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_deviation **deviations)
1347{
1348 struct lysp_deviation *dev;
1349
1350 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
1351
1352 /* store nodeid */
1353 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1354 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &dev->nodeid));
1355
1356 /* parse substatements */
1357 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1358 switch (child->kw) {
1359 case LY_STMT_DESCRIPTION:
1360 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
1361 break;
1362 case LY_STMT_DEVIATE:
1363 LY_CHECK_RET(lysp_stmt_deviate(ctx, child, &dev->deviates, &dev->exts));
1364 break;
1365 case LY_STMT_REFERENCE:
1366 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &dev->ref, Y_STR_ARG, &dev->exts));
1367 break;
1368 case LY_STMT_EXTENSION_INSTANCE:
1369 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &dev->exts));
1370 break;
1371 default:
1372 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_DEVIATION));
1373 return LY_EVALID;
1374 }
1375 }
1376
1377 return LY_SUCCESS;
1378}
1379
1380/**
1381 * @brief Parse the yang-version statement.
1382 *
1383 * @param[in] ctx parser context.
1384 * @param[in] stmt Source statement data from the parsed extension instance.
1385 * @param[out] version Version to write to.
1386 * @param[in,out] exts Extension instances to add to.
1387 * @return LY_ERR values.
1388 */
1389static LY_ERR
1390lysp_stmt_yangver(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *version, struct lysp_ext_instance **exts)
1391{
1392 if (*version) {
1393 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1394 return LY_EVALID;
1395 }
1396
1397 /* store flag */
1398 if (!strcmp(stmt->arg, "1")) {
1399 *version = LYS_VERSION_1_0;
1400 } else if (!strcmp(stmt->arg, "1.1")) {
1401 *version = LYS_VERSION_1_1;
1402 } else {
1403 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yang-version");
1404 return LY_EVALID;
1405 }
1406
1407 /* parse substatements */
1408 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1409 switch (child->kw) {
1410 case LY_STMT_EXTENSION_INSTANCE:
1411 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1412 break;
1413 default:
1414 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YANG_VERSION));
1415 return LY_EVALID;
1416 }
1417 }
1418
1419 return LY_SUCCESS;
1420}
1421
1422/**
1423 * @brief Parse the module statement.
1424 *
1425 * @param[in] ctx parser context.
1426 * @param[in] stmt Source statement data from the parsed extension instance.
1427 * @param[in,out] mod Module to fill.
1428 * @return LY_ERR values.
1429 */
1430static LY_ERR
1431lysp_stmt_module(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_module *mod)
1432{
1433 (void)stmt;
1434 (void)mod;
1435
1436 /* TODO */
1437 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"module\" substatement is not supported.");
1438 return LY_EINVAL;
1439}
1440
1441/**
1442 * @brief Parse the submodule statement.
1443 *
1444 * @param[in] ctx parser context.
1445 * @param[in] stmt Source statement data from the parsed extension instance.
1446 * @param[in,out] submod Module to fill.
1447 * @return LY_ERR values.
1448 */
1449static LY_ERR
1450lysp_stmt_submodule(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_submodule *submod)
1451{
1452 (void)stmt;
1453 (void)submod;
1454
1455 /* TODO */
1456 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "Extension instance \"submodule\" substatement is not supported.");
1457 return LY_EINVAL;
1458}
1459
1460/**
1461 * @brief Parse the yin-element statement. Substatement of argument statement.
1462 *
1463 * @param[in] ctx parser context.
1464 * @param[in] stmt Source statement data from the parsed extension instance.
1465 * @param[in,out] flags Flags to write to.
1466 * @param[in,out] exts Extension instances to add to.
1467 * @return LY_ERR values.
1468 */
1469static LY_ERR
1470lysp_stmt_yinelem(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
1471{
1472 if (*flags & LYS_YINELEM_MASK) {
1473 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
1474 return LY_EVALID;
1475 }
1476
1477 /* store flag */
1478 if (!strcmp(stmt->arg, "true")) {
1479 *flags |= LYS_YINELEM_TRUE;
1480 } else if (!strcmp(stmt->arg, "false")) {
1481 *flags |= LYS_YINELEM_FALSE;
1482 } else {
1483 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, strlen(stmt->arg), stmt->arg, "yin-element");
1484 return LY_EVALID;
1485 }
1486
1487 /* parse substatements */
1488 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1489 switch (child->kw) {
1490 case LY_STMT_EXTENSION_INSTANCE:
1491 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, exts));
1492 break;
1493 default:
1494 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_YIN_ELEMENT));
1495 return LY_EVALID;
1496 }
1497 }
1498
1499 return LY_SUCCESS;
1500}
1501
1502/**
1503 * @brief Parse the argument statement. Substatement of extension statement.
1504 *
1505 * @param[in] ctx parser context.
1506 * @param[in] stmt Source statement data from the parsed extension instance.
1507 * @param[in,out] ex Extension to fill.
1508 * @return LY_ERR values.
1509 */
1510static LY_ERR
1511lysp_stmt_argument(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext *ex)
1512{
1513 if (ex->argname) {
1514 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
1515 return LY_EVALID;
1516 }
1517
1518 /* store argument name */
1519 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
1520 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->argname));
1521
1522 /* parse substatements */
1523 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1524 switch (child->kw) {
1525 case LY_STMT_YIN_ELEMENT:
1526 LY_CHECK_RET(lysp_stmt_yinelem(ctx, child, &ex->flags, &ex->exts));
1527 break;
1528 case LY_STMT_EXTENSION_INSTANCE:
1529 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1530 break;
1531 default:
1532 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_ARGUMENT));
1533 return LY_EVALID;
1534 }
1535 }
1536
1537 return LY_SUCCESS;
1538}
1539
1540/**
1541 * @brief Parse the extension statement.
1542 *
1543 * @param[in] ctx parser context.
1544 * @param[in] stmt Source statement data from the parsed extension instance.
1545 * @param[in,out] extensions Array of extensions to add to.
1546 * @return LY_ERR values.
1547 */
1548static LY_ERR
1549lysp_stmt_extension(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ext **extensions)
1550{
1551 struct lysp_ext *ex;
1552
1553 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
1554
1555 /* store name */
1556 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1557 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ex->name));
1558
1559 /* parse substatements */
1560 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1561 switch (child->kw) {
1562 case LY_STMT_DESCRIPTION:
1563 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
1564 break;
1565 case LY_STMT_REFERENCE:
1566 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ex->ref, Y_STR_ARG, &ex->exts));
1567 break;
1568 case LY_STMT_STATUS:
1569 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ex->flags, &ex->exts));
1570 break;
1571 case LY_STMT_ARGUMENT:
1572 LY_CHECK_RET(lysp_stmt_argument(ctx, child, ex));
1573 break;
1574 case LY_STMT_EXTENSION_INSTANCE:
1575 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ex->exts));
1576 break;
1577 default:
1578 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_EXTENSION));
1579 return LY_EVALID;
1580 }
1581 }
1582
1583 return LY_SUCCESS;
1584}
1585
1586/**
1587 * @brief Parse the feature statement.
1588 *
1589 * @param[in] ctx parser context.
1590 * @param[in] stmt Source statement data from the parsed extension instance.
1591 * @param[in,out] features Array of features to add to.
1592 * @return LY_ERR values.
1593 */
1594static LY_ERR
1595lysp_stmt_feature(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_feature **features)
1596{
1597 struct lysp_feature *feat;
1598
1599 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
1600
1601 /* store name */
1602 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1603 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &feat->name));
1604
1605 /* parse substatements */
1606 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1607 switch (child->kw) {
1608 case LY_STMT_DESCRIPTION:
1609 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
1610 break;
1611 case LY_STMT_IF_FEATURE:
1612 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &feat->iffeatures, Y_STR_ARG, &feat->exts));
1613 break;
1614 case LY_STMT_REFERENCE:
1615 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &feat->ref, Y_STR_ARG, &feat->exts));
1616 break;
1617 case LY_STMT_STATUS:
1618 LY_CHECK_RET(lysp_stmt_status(ctx, child, &feat->flags, &feat->exts));
1619 break;
1620 case LY_STMT_EXTENSION_INSTANCE:
1621 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &feat->exts));
1622 break;
1623 default:
1624 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_FEATURE));
1625 return LY_EVALID;
1626 }
1627 }
1628
1629 return LY_SUCCESS;
1630}
1631
1632/**
1633 * @brief Parse the identity statement.
1634 *
1635 * @param[in] ctx parser context.
1636 * @param[in] stmt Source statement data from the parsed extension instance.
1637 * @param[in,out] identities Array of identities to add to.
1638 * @return LY_ERR values.
1639 */
1640static LY_ERR
1641lysp_stmt_identity(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_ident **identities)
1642{
1643 struct lysp_ident *ident;
1644
1645 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
1646
1647 /* store name */
1648 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1649 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &ident->name));
1650
1651 /* parse substatements */
1652 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1653 switch (child->kw) {
1654 case LY_STMT_DESCRIPTION:
1655 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
1656 break;
1657 case LY_STMT_IF_FEATURE:
1658 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &ident->iffeatures, Y_STR_ARG, &ident->exts));
1659 break;
1660 case LY_STMT_REFERENCE:
1661 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &ident->ref, Y_STR_ARG, &ident->exts));
1662 break;
1663 case LY_STMT_STATUS:
1664 LY_CHECK_RET(lysp_stmt_status(ctx, child, &ident->flags, &ident->exts));
1665 break;
1666 case LY_STMT_BASE:
1667 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
1668 break;
1669 case LY_STMT_EXTENSION_INSTANCE:
1670 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &ident->exts));
1671 break;
1672 default:
1673 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IDENTITY));
1674 return LY_EVALID;
1675 }
1676 }
1677
1678 return LY_SUCCESS;
1679}
1680
1681/**
1682 * @brief Parse the import statement.
1683 *
1684 * @param[in] ctx parser context.
1685 * @param[in] stmt Source statement data from the parsed extension instance.
1686 * @param[in,out] imports Array of imports to add to.
1687 * @return LY_ERR values.
1688 */
1689static LY_ERR
1690lysp_stmt_import(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_import **imports)
1691{
1692 struct lysp_import *imp;
1693 const char *str = NULL;
1694
1695 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EMEM);
1696
1697 /* store name */
1698 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1699 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &imp->name));
1700
1701 /* parse substatements */
1702 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1703 switch (child->kw) {
1704 case LY_STMT_PREFIX:
1705 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
1706 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, NULL, &imp->prefix), LY_EVALID);
1707 break;
1708 case LY_STMT_DESCRIPTION:
1709 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
1710 break;
1711 case LY_STMT_REFERENCE:
1712 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &imp->ref, Y_STR_ARG, &imp->exts));
1713 break;
1714 case LY_STMT_REVISION_DATE:
1715 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &imp->exts));
1716 strcpy(imp->rev, str);
1717 lydict_remove(PARSER_CTX(ctx), str);
1718 LY_CHECK_RET(lysp_check_date(ctx, imp->rev, LY_REV_SIZE - 1, "revision-date"));
1719 break;
1720 case LY_STMT_EXTENSION_INSTANCE:
1721 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &imp->exts));
1722 break;
1723 default:
1724 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_IMPORT));
1725 return LY_EVALID;
1726 }
1727 }
1728
1729 return LY_SUCCESS;
1730}
1731
1732/**
1733 * @brief Parse the include statement.
1734 *
1735 * @param[in] ctx parser context.
1736 * @param[in] stmt Source statement data from the parsed extension instance.
1737 * @param[in,out] includes Array of identities to add to.
1738 * @return LY_ERR values.
1739 */
1740static LY_ERR
1741lysp_stmt_include(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_include **includes)
1742{
1743 struct lysp_include *inc;
1744 const char *str = NULL;
1745
1746 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
1747
1748 /* store name */
1749 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1750 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &inc->name));
1751
1752 /* parse substatements */
1753 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1754 switch (child->kw) {
1755 case LY_STMT_DESCRIPTION:
1756 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
1757 break;
1758 case LY_STMT_REFERENCE:
1759 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &inc->ref, Y_STR_ARG, &inc->exts));
1760 break;
1761 case LY_STMT_REVISION_DATE:
1762 LY_CHECK_RET(lysp_stmt_text_field(ctx, stmt, 0, &str, Y_STR_ARG, &inc->exts));
1763 strcpy(inc->rev, str);
1764 lydict_remove(PARSER_CTX(ctx), str);
1765 LY_CHECK_RET(lysp_check_date(ctx, inc->rev, LY_REV_SIZE - 1, "revision-date"));
1766 break;
1767 case LY_STMT_EXTENSION_INSTANCE:
1768 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inc->exts));
1769 break;
1770 default:
1771 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_INCLUDE));
1772 return LY_EVALID;
1773 }
1774 }
1775
1776 return LY_SUCCESS;
1777}
1778
1779/**
1780 * @brief Parse the revision statement.
1781 *
1782 * @param[in] ctx parser context.
1783 * @param[in] stmt Source statement data from the parsed extension instance.
1784 * @param[in,out] includes Array of identities to add to.
1785 * @return LY_ERR values.
1786 */
1787static LY_ERR
1788lysp_stmt_revision(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_revision **revs)
1789{
1790 struct lysp_revision *rev;
1791
1792 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
1793
1794 /* store date */
Michal Vaskob425bb32022-11-08 10:49:36 +01001795 LY_CHECK_RET(lysp_check_date(ctx, stmt->arg, strlen(stmt->arg), "revision"));
Michal Vaskod5562c72022-11-08 11:30:50 +01001796 strncpy(rev->date, stmt->arg, LY_REV_SIZE - 1);
Michal Vasko193dacd2022-10-13 08:43:05 +02001797
1798 /* parse substatements */
1799 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1800 switch (child->kw) {
1801 case LY_STMT_DESCRIPTION:
1802 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
1803 break;
1804 case LY_STMT_REFERENCE:
1805 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rev->ref, Y_STR_ARG, &rev->exts));
1806 break;
1807 case LY_STMT_EXTENSION_INSTANCE:
1808 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &rev->exts));
1809 break;
1810 default:
1811 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(LY_STMT_REVISION));
1812 return LY_EVALID;
1813 }
1814 }
1815
1816 return LY_SUCCESS;
1817}
1818
1819/**
Radek Krejci335332a2019-09-05 13:03:35 +02001820 * @brief Parse the type statement.
1821 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001822 * @param[in] ctx parser context.
1823 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001824 * @param[in,out] type Type to wrote to.
1825 *
1826 * @return LY_ERR values.
1827 */
1828static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001829lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001830{
1831 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001832 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001833 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001834
1835 if (type->name) {
1836 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1837 return LY_EVALID;
1838 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001839
1840 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001841 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001842 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001843
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001844 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1845 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001846 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001847 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001848 type->flags |= LYS_SET_BASE;
1849 break;
1850 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001851 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001852 type->flags |= LYS_SET_BIT;
1853 break;
1854 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001855 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001856 type->flags |= LYS_SET_ENUM;
1857 break;
1858 case LY_STMT_FRACTION_DIGITS:
1859 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1860 type->flags |= LYS_SET_FRDIGITS;
1861 break;
1862 case LY_STMT_LENGTH:
1863 if (type->length) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001864 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001865 return LY_EVALID;
1866 }
1867 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001868 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001869
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001870 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001871 type->flags |= LYS_SET_LENGTH;
1872 break;
1873 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001874 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001875 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001876 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001877 lydict_remove(PARSER_CTX(ctx), str_path);
1878 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001879 type->flags |= LYS_SET_PATH;
1880 break;
1881 case LY_STMT_PATTERN:
1882 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1883 type->flags |= LYS_SET_PATTERN;
1884 break;
1885 case LY_STMT_RANGE:
1886 if (type->range) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001887 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001888 return LY_EVALID;
1889 }
1890 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001891 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001892
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001893 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001894 type->flags |= LYS_SET_RANGE;
1895 break;
1896 case LY_STMT_REQUIRE_INSTANCE:
1897 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001898 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001899 break;
1900 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001901 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001902 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1903 type->flags |= LYS_SET_TYPE;
1904 break;
1905 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001906 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001907 break;
1908 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001909 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001910 return LY_EVALID;
1911 }
1912 }
1913 return LY_SUCCESS;
1914}
1915
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001916/**
1917 * @brief Parse the leaf statement.
1918 *
1919 * @param[in] ctx parser context.
1920 * @param[in] stmt Source statement data from the parsed extension instance.
1921 * @param[in] parent Parent node to connect to (not into).
1922 * @param[in,out] siblings Siblings to add to.
1923 *
1924 * @return LY_ERR values.
1925 */
1926static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001927lysp_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 +01001928{
1929 struct lysp_node_leaf *leaf;
1930
1931 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1932
1933 /* create new leaf structure */
1934 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1935 leaf->nodetype = LYS_LEAF;
1936 leaf->parent = parent;
1937
1938 /* get name */
1939 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1940
1941 /* parse substatements */
1942 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1943 switch (child->kw) {
1944 case LY_STMT_CONFIG:
1945 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1946 break;
1947 case LY_STMT_DEFAULT:
1948 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 +01001949 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001950 break;
1951 case LY_STMT_DESCRIPTION:
1952 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1953 break;
1954 case LY_STMT_IF_FEATURE:
1955 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1956 break;
1957 case LY_STMT_MANDATORY:
1958 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1959 break;
1960 case LY_STMT_MUST:
1961 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1962 break;
1963 case LY_STMT_REFERENCE:
1964 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1965 break;
1966 case LY_STMT_STATUS:
1967 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1968 break;
1969 case LY_STMT_TYPE:
1970 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1971 break;
1972 case LY_STMT_UNITS:
1973 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1974 break;
1975 case LY_STMT_WHEN:
1976 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1977 break;
1978 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001979 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001980 break;
1981 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02001982 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "leaf");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001983 return LY_EVALID;
1984 }
1985 }
1986
1987 /* mandatory substatements */
1988 if (!leaf->type.name) {
1989 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1990 return LY_EVALID;
1991 }
1992
1993 return LY_SUCCESS;
1994}
1995
1996/**
1997 * @brief Parse the max-elements statement.
1998 *
1999 * @param[in] ctx parser context.
2000 * @param[in] stmt Source statement data from the parsed extension instance.
2001 * @param[in,out] max Value to write to.
2002 * @param[in,out] flags Flags to write to.
2003 * @param[in,out] exts Extension instances to add to.
2004 *
2005 * @return LY_ERR values.
2006 */
2007static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002008lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *max, uint16_t *flags,
2009 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002010{
2011 size_t arg_len;
2012 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002013 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002014
2015 if (*flags & LYS_SET_MAX) {
2016 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
2017 return LY_EVALID;
2018 }
2019 *flags |= LYS_SET_MAX;
2020
2021 /* get value */
2022 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2023 arg_len = strlen(stmt->arg);
2024
2025 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
2026 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
2027 return LY_EVALID;
2028 }
2029
2030 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
2031 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002032 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002033 /* we have not parsed the whole argument */
2034 if ((size_t)(ptr - stmt->arg) != arg_len) {
2035 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
2036 return LY_EVALID;
2037 }
2038 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2039 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
2040 return LY_EVALID;
2041 }
2042
2043 *max = num;
2044 } else {
2045 /* unbounded */
2046 *max = 0;
2047 }
2048
2049 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2050 switch (child->kw) {
2051 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002052 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002053 break;
2054 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002055 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "max-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002056 return LY_EVALID;
2057 }
2058 }
2059
2060 return LY_SUCCESS;
2061}
2062
2063/**
2064 * @brief Parse the min-elements statement.
2065 *
2066 * @param[in] ctx parser context.
2067 * @param[in] stmt Source statement data from the parsed extension instance.
2068 * @param[in,out] min Value to write to.
2069 * @param[in,out] flags Flags to write to.
2070 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002071 * @return LY_ERR values.
2072 */
2073static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002074lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t *min, uint16_t *flags,
2075 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002076{
2077 size_t arg_len;
2078 char *ptr;
Michal Vasko2bf4af42023-01-04 12:08:38 +01002079 unsigned long long num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002080
2081 if (*flags & LYS_SET_MIN) {
2082 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
2083 return LY_EVALID;
2084 }
2085 *flags |= LYS_SET_MIN;
2086
2087 /* get value */
2088 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2089 arg_len = strlen(stmt->arg);
2090
2091 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
2092 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2093 return LY_EVALID;
2094 }
2095
2096 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002097 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002098 /* we have not parsed the whole argument */
2099 if ((size_t)(ptr - stmt->arg) != arg_len) {
2100 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
2101 return LY_EVALID;
2102 }
2103 if ((errno == ERANGE) || (num > UINT32_MAX)) {
2104 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
2105 return LY_EVALID;
2106 }
2107 *min = num;
2108
2109 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2110 switch (child->kw) {
2111 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002112 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002113 break;
2114 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002115 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "min-elements");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002116 return LY_EVALID;
2117 }
2118 }
2119
2120 return LY_SUCCESS;
2121}
2122
2123/**
2124 * @brief Parse the ordered-by statement.
2125 *
2126 * @param[in] ctx parser context.
2127 * @param[in] stmt Source statement data from the parsed extension instance.
2128 * @param[in,out] flags Flags to write to.
2129 * @param[in,out] exts Extension instances to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002130 * @return LY_ERR values.
2131 */
2132static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002133lysp_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 +01002134{
2135 size_t arg_len;
2136
2137 if (*flags & LYS_ORDBY_MASK) {
2138 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
2139 return LY_EVALID;
2140 }
2141
2142 /* get value */
2143 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2144 arg_len = strlen(stmt->arg);
2145 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
2146 *flags |= LYS_MAND_TRUE;
2147 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
2148 *flags |= LYS_MAND_FALSE;
2149 } else {
2150 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
2151 return LY_EVALID;
2152 }
2153
2154 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2155 switch (child->kw) {
2156 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002157 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002158 break;
2159 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002160 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "ordered-by");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002161 return LY_EVALID;
2162 }
2163 }
2164
2165 return LY_SUCCESS;
2166}
2167
2168/**
2169 * @brief Parse the leaf-list statement.
2170 *
2171 * @param[in] ctx parser context.
2172 * @param[in] stmt Source statement data from the parsed extension instance.
2173 * @param[in] parent Parent node to connect to (not into).
2174 * @param[in,out] siblings Siblings to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002175 * @return LY_ERR values.
2176 */
2177static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002178lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002179 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002180{
2181 struct lysp_node_leaflist *llist;
2182
2183 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2184
2185 /* create new leaf-list structure */
2186 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
2187 llist->nodetype = LYS_LEAFLIST;
2188 llist->parent = parent;
2189
2190 /* get name */
2191 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
2192
2193 /* parse substatements */
2194 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2195 switch (child->kw) {
2196 case LY_STMT_CONFIG:
2197 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
2198 break;
2199 case LY_STMT_DEFAULT:
2200 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
2201 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
2202 break;
2203 case LY_STMT_DESCRIPTION:
2204 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
2205 break;
2206 case LY_STMT_IF_FEATURE:
2207 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
2208 break;
2209 case LY_STMT_MAX_ELEMENTS:
2210 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
2211 break;
2212 case LY_STMT_MIN_ELEMENTS:
2213 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
2214 break;
2215 case LY_STMT_MUST:
2216 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
2217 break;
2218 case LY_STMT_ORDERED_BY:
2219 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
2220 break;
2221 case LY_STMT_REFERENCE:
2222 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
2223 break;
2224 case LY_STMT_STATUS:
2225 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
2226 break;
2227 case LY_STMT_TYPE:
2228 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
2229 break;
2230 case LY_STMT_UNITS:
2231 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
2232 break;
2233 case LY_STMT_WHEN:
2234 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
2235 break;
2236 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002237 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002238 break;
2239 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002240 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "llist");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002241 return LY_EVALID;
2242 }
2243 }
2244
2245 /* mandatory substatements */
2246 if (!llist->type.name) {
2247 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
2248 return LY_EVALID;
2249 }
2250
2251 return LY_SUCCESS;
2252}
2253
2254/**
2255 * @brief Parse the refine statement.
2256 *
2257 * @param[in] ctx parser context.
2258 * @param[in] stmt Source statement data from the parsed extension instance.
2259 * @param[in,out] refines Refines to add to.
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002260 * @return LY_ERR values.
2261 */
2262static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002263lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002264{
2265 struct lysp_refine *rf;
2266
2267 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2268
2269 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
2270
2271 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
2272
2273 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2274 switch (child->kw) {
2275 case LY_STMT_CONFIG:
2276 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
2277 break;
2278 case LY_STMT_DEFAULT:
2279 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
2280 break;
2281 case LY_STMT_DESCRIPTION:
2282 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
2283 break;
2284 case LY_STMT_IF_FEATURE:
2285 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
2286 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
2287 break;
2288 case LY_STMT_MAX_ELEMENTS:
2289 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
2290 break;
2291 case LY_STMT_MIN_ELEMENTS:
2292 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
2293 break;
2294 case LY_STMT_MUST:
2295 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
2296 break;
2297 case LY_STMT_MANDATORY:
2298 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
2299 break;
2300 case LY_STMT_REFERENCE:
2301 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
2302 break;
2303 case LY_STMT_PRESENCE:
2304 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
2305 break;
2306 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002307 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002308 break;
2309 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002310 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "refine");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002311 return LY_EVALID;
2312 }
2313 }
2314
2315 return LY_SUCCESS;
2316}
2317
2318/**
2319 * @brief Parse the typedef statement.
2320 *
2321 * @param[in] ctx parser context.
2322 * @param[in] stmt Source statement data from the parsed extension instance.
2323 * @param[in] parent Parent node to connect to (not into).
2324 * @param[in,out] typedefs Typedefs to add to.
2325 *
2326 * @return LY_ERR values.
2327 */
2328static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002329lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002330 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002331{
2332 struct lysp_tpdf *tpdf;
2333
2334 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2335
2336 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
2337
2338 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
2339
2340 /* parse substatements */
2341 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2342 switch (child->kw) {
2343 case LY_STMT_DEFAULT:
2344 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 +01002345 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002346 break;
2347 case LY_STMT_DESCRIPTION:
2348 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
2349 break;
2350 case LY_STMT_REFERENCE:
2351 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
2352 break;
2353 case LY_STMT_STATUS:
2354 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
2355 break;
2356 case LY_STMT_TYPE:
2357 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
2358 break;
2359 case LY_STMT_UNITS:
2360 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
2361 break;
2362 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002363 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002364 break;
2365 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002366 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "typedef");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002367 return LY_EVALID;
2368 }
2369 }
2370
2371 /* mandatory substatements */
2372 if (!tpdf->type.name) {
2373 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
2374 return LY_EVALID;
2375 }
2376
2377 /* store data for collision check */
2378 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
2379 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
2380 }
2381
2382 return LY_SUCCESS;
2383}
2384
2385/**
2386 * @brief Parse the input or output statement.
2387 *
2388 * @param[in] ctx parser context.
2389 * @param[in] stmt Source statement data from the parsed extension instance.
2390 * @param[in] parent Parent node to connect to (not into).
2391 * @param[in,out] inout_p Input/output pointer to write to.
2392 *
2393 * @return LY_ERR values.
2394 */
2395static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002396lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002397 struct lysp_node_action_inout *inout_p)
2398{
2399 if (inout_p->nodetype) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002400 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002401 return LY_EVALID;
2402 }
2403
2404 /* initiate structure */
2405 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
2406 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
2407 inout_p->parent = parent;
2408
2409 /* parse substatements */
2410 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2411 switch (child->kw) {
2412 case LY_STMT_ANYDATA:
Michal Vasko193dacd2022-10-13 08:43:05 +02002413 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002414 /* fall through */
2415 case LY_STMT_ANYXML:
2416 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
2417 break;
2418 case LY_STMT_CHOICE:
2419 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
2420 break;
2421 case LY_STMT_CONTAINER:
2422 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
2423 break;
2424 case LY_STMT_LEAF:
2425 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
2426 break;
2427 case LY_STMT_LEAF_LIST:
2428 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
2429 break;
2430 case LY_STMT_LIST:
2431 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
2432 break;
2433 case LY_STMT_USES:
2434 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
2435 break;
2436 case LY_STMT_TYPEDEF:
2437 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
2438 break;
2439 case LY_STMT_MUST:
Michal Vasko193dacd2022-10-13 08:43:05 +02002440 PARSER_CHECK_STMTVER2_RET(ctx, "must", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002441 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
2442 break;
2443 case LY_STMT_GROUPING:
2444 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
2445 break;
2446 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002447 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002448 break;
2449 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002450 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002451 return LY_EVALID;
2452 }
2453 }
2454
2455 if (!inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002456 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(stmt->kw));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002457 return LY_EVALID;
2458 }
2459
2460 return LY_SUCCESS;
2461}
2462
2463/**
2464 * @brief Parse the action statement.
2465 *
2466 * @param[in] ctx parser context.
2467 * @param[in] stmt Source statement data from the parsed extension instance.
2468 * @param[in] parent Parent node to connect to (not into).
2469 * @param[in,out] actions Actions to add to.
2470 *
2471 * @return LY_ERR values.
2472 */
2473static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002474lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002475 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002476{
2477 struct lysp_node_action *act;
2478
2479 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2480
2481 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
2482
2483 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
2484 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
2485 act->parent = parent;
2486
2487 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2488 switch (child->kw) {
2489 case LY_STMT_DESCRIPTION:
2490 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
2491 break;
2492 case LY_STMT_IF_FEATURE:
2493 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
2494 break;
2495 case LY_STMT_REFERENCE:
2496 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
2497 break;
2498 case LY_STMT_STATUS:
2499 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
2500 break;
2501
2502 case LY_STMT_INPUT:
2503 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
2504 break;
2505 case LY_STMT_OUTPUT:
2506 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
2507 break;
2508
2509 case LY_STMT_TYPEDEF:
2510 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
2511 break;
2512 case LY_STMT_GROUPING:
2513 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
2514 break;
2515 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002516 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 +01002517 break;
2518 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002519 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), parent ? "action" : "rpc");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002520 return LY_EVALID;
2521 }
2522 }
2523
2524 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2525 if (!act->input.nodetype) {
2526 act->input.nodetype = LYS_INPUT;
2527 act->input.parent = &act->node;
2528 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2529 }
2530 if (!act->output.nodetype) {
2531 act->output.nodetype = LYS_OUTPUT;
2532 act->output.parent = &act->node;
2533 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2534 }
2535
2536 return LY_SUCCESS;
2537}
2538
2539/**
2540 * @brief Parse the notification statement.
2541 *
2542 * @param[in] ctx parser context.
2543 * @param[in] stmt Source statement data from the parsed extension instance.
2544 * @param[in] parent Parent node to connect to (not into).
2545 * @param[in,out] notifs Notifications to add to.
2546 *
2547 * @return LY_ERR values.
2548 */
2549static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002550lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002551 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002552{
2553 struct lysp_node_notif *notif;
2554
2555 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2556
2557 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
2558
2559 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
2560 notif->nodetype = LYS_NOTIF;
2561 notif->parent = parent;
2562
2563 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2564 switch (child->kw) {
2565 case LY_STMT_DESCRIPTION:
2566 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
2567 break;
2568 case LY_STMT_IF_FEATURE:
2569 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
2570 break;
2571 case LY_STMT_REFERENCE:
2572 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
2573 break;
2574 case LY_STMT_STATUS:
2575 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
2576 break;
2577
2578 case LY_STMT_ANYDATA:
2579 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
2580 /* fall through */
2581 case LY_STMT_ANYXML:
2582 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
2583 break;
2584 case LY_STMT_CHOICE:
2585 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
2586 break;
2587 case LY_STMT_CONTAINER:
2588 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
2589 break;
2590 case LY_STMT_LEAF:
2591 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
2592 break;
2593 case LY_STMT_LEAF_LIST:
2594 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
2595 break;
2596 case LY_STMT_LIST:
2597 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
2598 break;
2599 case LY_STMT_USES:
2600 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
2601 break;
2602
2603 case LY_STMT_MUST:
2604 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
2605 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
2606 break;
2607 case LY_STMT_TYPEDEF:
2608 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
2609 break;
2610 case LY_STMT_GROUPING:
2611 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
2612 break;
2613 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002614 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002615 break;
2616 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002617 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "notification");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002618 return LY_EVALID;
2619 }
2620 }
2621
2622 return LY_SUCCESS;
2623}
2624
2625/**
2626 * @brief Parse the grouping statement.
2627 *
2628 * @param[in] ctx parser context.
2629 * @param[in] stmt Source statement data from the parsed extension instance.
2630 * @param[in] parent Parent node to connect to (not into).
2631 * @param[in,out] groupings Groupings to add to.
2632 *
2633 * @return LY_ERR values.
2634 */
2635static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002636lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002637 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002638{
2639 struct lysp_node_grp *grp;
2640
2641 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2642
2643 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
2644
2645 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
2646 grp->nodetype = LYS_GROUPING;
2647 grp->parent = parent;
2648
2649 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2650 switch (child->kw) {
2651 case LY_STMT_DESCRIPTION:
2652 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
2653 break;
2654 case LY_STMT_REFERENCE:
2655 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
2656 break;
2657 case LY_STMT_STATUS:
2658 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
2659 break;
2660
2661 case LY_STMT_ANYDATA:
2662 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
2663 /* fall through */
2664 case LY_STMT_ANYXML:
2665 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
2666 break;
2667 case LY_STMT_CHOICE:
2668 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
2669 break;
2670 case LY_STMT_CONTAINER:
2671 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
2672 break;
2673 case LY_STMT_LEAF:
2674 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
2675 break;
2676 case LY_STMT_LEAF_LIST:
2677 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
2678 break;
2679 case LY_STMT_LIST:
2680 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2681 break;
2682 case LY_STMT_USES:
2683 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2684 break;
2685
2686 case LY_STMT_TYPEDEF:
2687 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2688 break;
2689 case LY_STMT_ACTION:
2690 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2691 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2692 break;
2693 case LY_STMT_GROUPING:
2694 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2695 break;
2696 case LY_STMT_NOTIFICATION:
2697 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2698 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2699 break;
2700 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002701 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002702 break;
2703 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002704 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "grouping");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002705 return LY_EVALID;
2706 }
2707 }
2708
2709 return LY_SUCCESS;
2710}
2711
2712/**
2713 * @brief Parse the augment statement.
2714 *
2715 * @param[in] ctx parser context.
2716 * @param[in] stmt Source statement data from the parsed extension instance.
2717 * @param[in] parent Parent node to connect to (not into).
2718 * @param[in,out] augments Augments to add to.
2719 *
2720 * @return LY_ERR values.
2721 */
2722static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002723lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002724 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002725{
2726 struct lysp_node_augment *aug;
2727
2728 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2729
2730 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2731
2732 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2733 aug->nodetype = LYS_AUGMENT;
2734 aug->parent = parent;
2735
2736 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2737 switch (child->kw) {
2738 case LY_STMT_DESCRIPTION:
2739 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2740 break;
2741 case LY_STMT_IF_FEATURE:
2742 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2743 break;
2744 case LY_STMT_REFERENCE:
2745 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2746 break;
2747 case LY_STMT_STATUS:
2748 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2749 break;
2750 case LY_STMT_WHEN:
2751 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2752 break;
2753
2754 case LY_STMT_ANYDATA:
2755 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2756 /* fall through */
2757 case LY_STMT_ANYXML:
2758 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2759 break;
2760 case LY_STMT_CASE:
2761 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2762 break;
2763 case LY_STMT_CHOICE:
2764 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2765 break;
2766 case LY_STMT_CONTAINER:
2767 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2768 break;
2769 case LY_STMT_LEAF:
2770 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2771 break;
2772 case LY_STMT_LEAF_LIST:
2773 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2774 break;
2775 case LY_STMT_LIST:
2776 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2777 break;
2778 case LY_STMT_USES:
2779 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2780 break;
2781
2782 case LY_STMT_ACTION:
2783 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2784 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2785 break;
2786 case LY_STMT_NOTIFICATION:
2787 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2788 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2789 break;
2790 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002791 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002792 break;
2793 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002794 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "augment");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002795 return LY_EVALID;
2796 }
2797 }
2798
2799 return LY_SUCCESS;
2800}
2801
2802/**
2803 * @brief Parse the uses statement.
2804 *
2805 * @param[in] ctx parser context.
2806 * @param[in] stmt Source statement data from the parsed extension instance.
2807 * @param[in] parent Parent node to connect to (not into).
2808 * @param[in,out] siblings Siblings to add to.
2809 *
2810 * @return LY_ERR values.
2811 */
2812static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002813lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002814 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002815{
2816 struct lysp_node_uses *uses;
2817
2818 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2819
2820 /* create uses structure */
2821 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2822
2823 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2824 uses->nodetype = LYS_USES;
2825 uses->parent = parent;
2826
2827 /* parse substatements */
2828 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2829 switch (child->kw) {
2830 case LY_STMT_DESCRIPTION:
2831 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2832 break;
2833 case LY_STMT_IF_FEATURE:
2834 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2835 break;
2836 case LY_STMT_REFERENCE:
2837 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2838 break;
2839 case LY_STMT_STATUS:
2840 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2841 break;
2842 case LY_STMT_WHEN:
2843 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2844 break;
2845
2846 case LY_STMT_REFINE:
2847 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2848 break;
2849 case LY_STMT_AUGMENT:
2850 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2851 break;
2852 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002853 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002854 break;
2855 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002856 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "uses");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002857 return LY_EVALID;
2858 }
2859 }
2860
2861 return LY_SUCCESS;
2862}
2863
2864/**
2865 * @brief Parse the case statement.
2866 *
2867 * @param[in] ctx parser context.
2868 * @param[in] stmt Source statement data from the parsed extension instance.
2869 * @param[in] parent Parent node to connect to (not into).
2870 * @param[in,out] siblings Siblings to add to.
2871 *
2872 * @return LY_ERR values.
2873 */
2874static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002875lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002876 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002877{
2878 struct lysp_node_case *cas;
2879
2880 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2881
2882 /* create new case structure */
2883 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2884
2885 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2886 cas->nodetype = LYS_CASE;
2887 cas->parent = parent;
2888
2889 /* parse substatements */
2890 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2891 switch (child->kw) {
2892 case LY_STMT_DESCRIPTION:
2893 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2894 break;
2895 case LY_STMT_IF_FEATURE:
2896 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2897 break;
2898 case LY_STMT_REFERENCE:
2899 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2900 break;
2901 case LY_STMT_STATUS:
2902 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2903 break;
2904 case LY_STMT_WHEN:
2905 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2906 break;
2907
2908 case LY_STMT_ANYDATA:
2909 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2910 /* fall through */
2911 case LY_STMT_ANYXML:
2912 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2913 break;
2914 case LY_STMT_CHOICE:
2915 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2916 break;
2917 case LY_STMT_CONTAINER:
2918 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2919 break;
2920 case LY_STMT_LEAF:
2921 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2922 break;
2923 case LY_STMT_LEAF_LIST:
2924 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2925 break;
2926 case LY_STMT_LIST:
2927 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2928 break;
2929 case LY_STMT_USES:
2930 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2931 break;
2932 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002933 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002934 break;
2935 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02002936 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "case");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002937 return LY_EVALID;
2938 }
2939 }
2940 return LY_SUCCESS;
2941}
2942
2943/**
2944 * @brief Parse the choice statement.
2945 *
2946 * @param[in] ctx parser context.
2947 * @param[in] stmt Source statement data from the parsed extension instance.
2948 * @param[in] parent Parent node to connect to (not into).
2949 * @param[in,out] siblings Siblings to add to.
2950 *
2951 * @return LY_ERR values.
2952 */
2953static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002954lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002955 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002956{
2957 struct lysp_node_choice *choice;
2958
2959 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2960
2961 /* create new choice structure */
2962 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2963
2964 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2965 choice->nodetype = LYS_CHOICE;
2966 choice->parent = parent;
2967
2968 /* parse substatements */
2969 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2970 switch (child->kw) {
2971 case LY_STMT_CONFIG:
2972 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2973 break;
2974 case LY_STMT_DESCRIPTION:
2975 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2976 break;
2977 case LY_STMT_IF_FEATURE:
2978 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2979 break;
2980 case LY_STMT_MANDATORY:
2981 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2982 break;
2983 case LY_STMT_REFERENCE:
2984 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2985 break;
2986 case LY_STMT_STATUS:
2987 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2988 break;
2989 case LY_STMT_WHEN:
2990 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2991 break;
2992 case LY_STMT_DEFAULT:
2993 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 +01002994 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002995 break;
2996 case LY_STMT_ANYDATA:
2997 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2998 /* fall through */
2999 case LY_STMT_ANYXML:
3000 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
3001 break;
3002 case LY_STMT_CASE:
3003 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
3004 break;
3005 case LY_STMT_CHOICE:
3006 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
3007 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
3008 break;
3009 case LY_STMT_CONTAINER:
3010 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
3011 break;
3012 case LY_STMT_LEAF:
3013 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
3014 break;
3015 case LY_STMT_LEAF_LIST:
3016 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
3017 break;
3018 case LY_STMT_LIST:
3019 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
3020 break;
3021 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003022 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003023 break;
3024 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003025 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "choice");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003026 return LY_EVALID;
3027 }
3028 }
3029 return LY_SUCCESS;
3030}
3031
3032/**
3033 * @brief Parse the container statement.
3034 *
3035 * @param[in] ctx parser context.
3036 * @param[in] stmt Source statement data from the parsed extension instance.
3037 * @param[in] parent Parent node to connect to (not into).
3038 * @param[in,out] siblings Siblings to add to.
3039 *
3040 * @return LY_ERR values.
3041 */
3042static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003043lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003044 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003045{
3046 struct lysp_node_container *cont;
3047
3048 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3049
3050 /* create new container structure */
3051 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
3052
3053 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
3054 cont->nodetype = LYS_CONTAINER;
3055 cont->parent = parent;
3056
3057 /* parse substatements */
3058 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3059 switch (child->kw) {
3060 case LY_STMT_CONFIG:
3061 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
3062 break;
3063 case LY_STMT_DESCRIPTION:
3064 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
3065 break;
3066 case LY_STMT_IF_FEATURE:
3067 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
3068 break;
3069 case LY_STMT_REFERENCE:
3070 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
3071 break;
3072 case LY_STMT_STATUS:
3073 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
3074 break;
3075 case LY_STMT_WHEN:
3076 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
3077 break;
3078 case LY_STMT_PRESENCE:
3079 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
3080 break;
3081 case LY_STMT_ANYDATA:
3082 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
3083 /* fall through */
3084 case LY_STMT_ANYXML:
3085 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
3086 break;
3087 case LY_STMT_CHOICE:
3088 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
3089 break;
3090 case LY_STMT_CONTAINER:
3091 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
3092 break;
3093 case LY_STMT_LEAF:
3094 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
3095 break;
3096 case LY_STMT_LEAF_LIST:
3097 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
3098 break;
3099 case LY_STMT_LIST:
3100 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
3101 break;
3102 case LY_STMT_USES:
3103 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
3104 break;
3105
3106 case LY_STMT_TYPEDEF:
3107 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
3108 break;
3109 case LY_STMT_MUST:
3110 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
3111 break;
3112 case LY_STMT_ACTION:
3113 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
3114 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
3115 break;
3116 case LY_STMT_GROUPING:
3117 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
3118 break;
3119 case LY_STMT_NOTIFICATION:
3120 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
3121 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
3122 break;
3123 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003124 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003125 break;
3126 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003127 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "container");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003128 return LY_EVALID;
3129 }
3130 }
3131
3132 return LY_SUCCESS;
3133}
3134
3135/**
3136 * @brief Parse the list statement.
3137 *
3138 * @param[in] ctx parser context.
3139 * @param[in] stmt Source statement data from the parsed extension instance.
3140 * @param[in] parent Parent node to connect to (not into).
3141 * @param[in,out] siblings Siblings to add to.
3142 *
3143 * @return LY_ERR values.
3144 */
3145static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003146lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02003147 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003148{
3149 struct lysp_node_list *list;
3150
3151 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
3152
3153 /* create new list structure */
3154 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
3155
3156 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
3157 list->nodetype = LYS_LIST;
3158 list->parent = parent;
3159
3160 /* parse substatements */
3161 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
3162 switch (child->kw) {
3163 case LY_STMT_CONFIG:
3164 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
3165 break;
3166 case LY_STMT_DESCRIPTION:
3167 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
3168 break;
3169 case LY_STMT_IF_FEATURE:
3170 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
3171 break;
3172 case LY_STMT_REFERENCE:
3173 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
3174 break;
3175 case LY_STMT_STATUS:
3176 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
3177 break;
3178 case LY_STMT_WHEN:
3179 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
3180 break;
3181 case LY_STMT_KEY:
3182 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
3183 break;
3184 case LY_STMT_MAX_ELEMENTS:
3185 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
3186 break;
3187 case LY_STMT_MIN_ELEMENTS:
3188 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
3189 break;
3190 case LY_STMT_ORDERED_BY:
3191 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
3192 break;
3193 case LY_STMT_UNIQUE:
3194 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
3195 break;
3196
3197 case LY_STMT_ANYDATA:
3198 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
3199 /* fall through */
3200 case LY_STMT_ANYXML:
3201 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
3202 break;
3203 case LY_STMT_CHOICE:
3204 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
3205 break;
3206 case LY_STMT_CONTAINER:
3207 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
3208 break;
3209 case LY_STMT_LEAF:
3210 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
3211 break;
3212 case LY_STMT_LEAF_LIST:
3213 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
3214 break;
3215 case LY_STMT_LIST:
3216 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
3217 break;
3218 case LY_STMT_USES:
3219 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
3220 break;
3221
3222 case LY_STMT_TYPEDEF:
3223 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
3224 break;
3225 case LY_STMT_MUST:
3226 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
3227 break;
3228 case LY_STMT_ACTION:
3229 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
3230 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
3231 break;
3232 case LY_STMT_GROUPING:
3233 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
3234 break;
3235 case LY_STMT_NOTIFICATION:
3236 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
3237 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
3238 break;
3239 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003240 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003241 break;
3242 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003243 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, lyplg_ext_stmt2str(child->kw), "list");
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003244 return LY_EVALID;
3245 }
3246 }
3247
3248 return LY_SUCCESS;
3249}
3250
Michal Vasko193dacd2022-10-13 08:43:05 +02003251/**
3252 * @brief Parse generic statement structure into a specific parsed-schema structure.
3253 *
3254 * @param[in] pctx Parse context of the @p stmt being processed.
3255 * @param[in] stmt Generic statement structure to process.
3256 * @param[out] result Specific parsed-schema structure for the given statement. For the specific type for the particular statement, check the function code.
3257 * @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.
3258 * @return LY_ERR value.
3259 */
3260static LY_ERR
3261lysp_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 +02003262{
Radek Krejciad5963b2019-09-06 16:03:05 +02003263 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003264 uint16_t flags;
Radek Krejci335332a2019-09-05 13:03:35 +02003265
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003266 switch (stmt->kw) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003267 case LY_STMT_NOTIFICATION:
3268 ret = lysp_stmt_notif(pctx, stmt, NULL, (struct lysp_node_notif **)result);
3269 break;
3270 case LY_STMT_INPUT:
3271 case LY_STMT_OUTPUT: {
3272 struct lysp_node_action_inout *inout;
3273
3274 *result = inout = calloc(1, sizeof *inout);
3275 LY_CHECK_ERR_RET(!inout, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3276 ret = lysp_stmt_inout(pctx, stmt, NULL, inout);
3277 break;
3278 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003279 case LY_STMT_ACTION:
3280 case LY_STMT_RPC:
Michal Vasko193dacd2022-10-13 08:43:05 +02003281 ret = lysp_stmt_action(pctx, stmt, NULL, (struct lysp_node_action **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003282 break;
3283 case LY_STMT_ANYDATA:
3284 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003285 ret = lysp_stmt_any(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003286 break;
3287 case LY_STMT_AUGMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003288 ret = lysp_stmt_augment(pctx, stmt, NULL, (struct lysp_node_augment **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003289 break;
3290 case LY_STMT_CASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003291 ret = lysp_stmt_case(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003292 break;
3293 case LY_STMT_CHOICE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003294 ret = lysp_stmt_choice(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003295 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003296 case LY_STMT_CONTAINER:
3297 ret = lysp_stmt_container(pctx, stmt, NULL, (struct lysp_node **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003298 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003299 case LY_STMT_GROUPING:
3300 ret = lysp_stmt_grouping(pctx, stmt, NULL, (struct lysp_node_grp **)result);
3301 break;
3302 case LY_STMT_LEAF:
3303 ret = lysp_stmt_leaf(pctx, stmt, NULL, (struct lysp_node **)result);
3304 break;
3305 case LY_STMT_LEAF_LIST:
3306 ret = lysp_stmt_leaflist(pctx, stmt, NULL, (struct lysp_node **)result);
3307 break;
3308 case LY_STMT_LIST:
3309 ret = lysp_stmt_list(pctx, stmt, NULL, (struct lysp_node **)result);
3310 break;
3311 case LY_STMT_USES:
3312 ret = lysp_stmt_uses(pctx, stmt, NULL, (struct lysp_node **)result);
3313 break;
3314 case LY_STMT_BASE:
3315 ret = lysp_stmt_text_fields(pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
3316 break;
3317 case LY_STMT_ARGUMENT:
3318 case LY_STMT_BELONGS_TO:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003319 case LY_STMT_CONTACT:
3320 case LY_STMT_DESCRIPTION:
3321 case LY_STMT_ERROR_APP_TAG:
3322 case LY_STMT_ERROR_MESSAGE:
3323 case LY_STMT_KEY:
3324 case LY_STMT_NAMESPACE:
3325 case LY_STMT_ORGANIZATION:
3326 case LY_STMT_PRESENCE:
3327 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003328 case LY_STMT_REVISION_DATE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003329 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003330 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003331 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003332 case LY_STMT_BIT:
3333 case LY_STMT_ENUM:
3334 ret = lysp_stmt_type_enum(pctx, stmt, (struct lysp_type_enum **)result);
3335 break;
3336 case LY_STMT_CONFIG:
3337 assert(*result);
3338 ret = lysp_stmt_config(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003339 break;
3340 case LY_STMT_DEFAULT:
3341 case LY_STMT_IF_FEATURE:
3342 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003343 ret = lysp_stmt_qnames(pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
3344 break;
3345 case LY_STMT_DEVIATE:
3346 ret = lysp_stmt_deviate(pctx, stmt, (struct lysp_deviate **)result, exts);
3347 break;
3348 case LY_STMT_DEVIATION:
3349 ret = lysp_stmt_deviation(pctx, stmt, (struct lysp_deviation **)result);
3350 break;
3351 case LY_STMT_EXTENSION:
3352 ret = lysp_stmt_extension(pctx, stmt, (struct lysp_ext **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003353 break;
3354 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003355 ret = lysp_stmt_ext(pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, (struct lysp_ext_instance **)result);
3356 break;
3357 case LY_STMT_FEATURE:
3358 ret = lysp_stmt_feature(pctx, stmt, (struct lysp_feature **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003359 break;
3360 case LY_STMT_FRACTION_DIGITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003361 ret = lysp_stmt_type_fracdigits(pctx, stmt, *(uint8_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003362 break;
3363 case LY_STMT_LENGTH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003364 case LY_STMT_RANGE: {
3365 struct lysp_restr *restr;
3366
3367 *result = restr = calloc(1, sizeof *restr);
3368 LY_CHECK_ERR_RET(!restr, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3369
3370 ret = lysp_stmt_restr(pctx, stmt, restr);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003371 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003372 }
3373 case LY_STMT_MUST:
3374 ret = lysp_stmt_restrs(pctx, stmt, (struct lysp_restr **)result);
3375 break;
3376 case LY_STMT_IDENTITY:
3377 ret = lysp_stmt_identity(pctx, stmt, (struct lysp_ident **)result);
3378 break;
3379 case LY_STMT_IMPORT:
3380 ret = lysp_stmt_import(pctx, stmt, (struct lysp_import **)result);
3381 break;
3382 case LY_STMT_INCLUDE:
3383 ret = lysp_stmt_include(pctx, stmt, (struct lysp_include **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003384 break;
3385 case LY_STMT_MANDATORY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003386 ret = lysp_stmt_mandatory(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003387 break;
3388 case LY_STMT_MAX_ELEMENTS:
3389 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003390 ret = lysp_stmt_maxelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003391 break;
3392 case LY_STMT_MIN_ELEMENTS:
3393 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003394 ret = lysp_stmt_minelements(pctx, stmt, *(uint32_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003395 break;
3396 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003397 ret = lysp_stmt_type_pattern_modifier(pctx, stmt, (const char **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003398 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003399 case LY_STMT_MODULE: {
3400 struct lysp_module *mod;
3401
3402 *result = mod = calloc(1, sizeof *mod);
3403 LY_CHECK_ERR_RET(!mod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3404 ret = lysp_stmt_module(pctx, stmt, mod);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003405 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003406 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003407 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003408 ret = lysp_stmt_orderedby(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003409 break;
3410 case LY_STMT_PATH: {
3411 const char *str_path = NULL;
3412
Michal Vasko193dacd2022-10-13 08:43:05 +02003413 LY_CHECK_RET(lysp_stmt_text_field(pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
3414 ret = ly_path_parse(PARSER_CTX(pctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003415 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
Michal Vasko193dacd2022-10-13 08:43:05 +02003416 lydict_remove(PARSER_CTX(pctx), str_path);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003417 break;
3418 }
3419 case LY_STMT_PATTERN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003420 ret = lysp_stmt_type_pattern(pctx, stmt, (struct lysp_restr **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003421 break;
3422 case LY_STMT_POSITION:
3423 case LY_STMT_VALUE:
3424 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003425 ret = lysp_stmt_type_enum_value_pos(pctx, stmt, *(int64_t **)result, &flags, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003426 break;
3427 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003428 ret = lysp_stmt_text_field(pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003429 break;
3430 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003431 ret = lysp_stmt_refine(pctx, stmt, (struct lysp_refine **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003432 break;
3433 case LY_STMT_REQUIRE_INSTANCE:
3434 flags = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02003435 ret = lysp_stmt_type_reqinstance(pctx, stmt, *(uint8_t **)result, &flags, exts);
3436 break;
3437 case LY_STMT_REVISION:
3438 ret = lysp_stmt_revision(pctx, stmt, (struct lysp_revision **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003439 break;
Michal Vasko69730152020-10-09 16:30:07 +02003440 case LY_STMT_STATUS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003441 ret = lysp_stmt_status(pctx, stmt, (uint16_t *)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02003442 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003443 case LY_STMT_SUBMODULE: {
3444 struct lysp_submodule *submod;
3445
3446 *result = submod = calloc(1, sizeof *submod);
3447 LY_CHECK_ERR_RET(!submod, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3448 ret = lysp_stmt_submodule(pctx, stmt, submod);
3449 break;
3450 }
Radek Krejci335332a2019-09-05 13:03:35 +02003451 case LY_STMT_TYPE: {
3452 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02003453
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003454 *result = type = calloc(1, sizeof *type);
Michal Vasko193dacd2022-10-13 08:43:05 +02003455 LY_CHECK_ERR_RET(!type, LOGMEM(PARSER_CTX(pctx)), LY_EMEM);
3456 ret = lysp_stmt_type(pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02003457 break;
Radek Krejci0f969882020-08-21 16:56:47 +02003458 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003459 case LY_STMT_TYPEDEF:
Michal Vasko193dacd2022-10-13 08:43:05 +02003460 ret = lysp_stmt_typedef(pctx, stmt, NULL, (struct lysp_tpdf **)result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003461 break;
3462 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003463 ret = lysp_stmt_when(pctx, stmt, (struct lysp_when **)result);
3464 break;
3465 case LY_STMT_YANG_VERSION:
3466 ret = lysp_stmt_yangver(pctx, stmt, *(uint8_t **)result, exts);
3467 break;
3468 case LY_STMT_YIN_ELEMENT:
3469 ret = lysp_stmt_yinelem(pctx, stmt, *(uint16_t **)result, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01003470 break;
Radek Krejci335332a2019-09-05 13:03:35 +02003471 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003472 LOGINT(PARSER_CTX(pctx));
Radek Krejci335332a2019-09-05 13:03:35 +02003473 return LY_EINT;
3474 }
3475
Radek Krejciad5963b2019-09-06 16:03:05 +02003476 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02003477}
Michal Vasko59892dd2022-05-13 11:02:30 +02003478
Michal Vasko193dacd2022-10-13 08:43:05 +02003479LY_ERR
3480lys_parse_ext_instance_stmt(struct lysp_ctx *pctx, struct lysp_ext_substmt *substmt, struct lysp_stmt *stmt)
Michal Vasko59892dd2022-05-13 11:02:30 +02003481{
Michal Vasko193dacd2022-10-13 08:43:05 +02003482 LY_ERR rc = LY_SUCCESS;
Michal Vasko59892dd2022-05-13 11:02:30 +02003483
Michal Vasko193dacd2022-10-13 08:43:05 +02003484 if (!substmt->storage) {
3485 /* nothing to parse, ignored */
3486 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003487 }
3488
Michal Vasko193dacd2022-10-13 08:43:05 +02003489 switch (stmt->kw) {
3490 case LY_STMT_NOTIFICATION:
3491 case LY_STMT_INPUT:
3492 case LY_STMT_OUTPUT:
3493 case LY_STMT_ACTION:
3494 case LY_STMT_RPC:
3495 case LY_STMT_ANYDATA:
3496 case LY_STMT_ANYXML:
3497 case LY_STMT_AUGMENT:
3498 case LY_STMT_CASE:
3499 case LY_STMT_CHOICE:
3500 case LY_STMT_CONTAINER:
3501 case LY_STMT_GROUPING:
3502 case LY_STMT_LEAF:
3503 case LY_STMT_LEAF_LIST:
3504 case LY_STMT_LIST:
3505 case LY_STMT_USES: {
3506 struct lysp_node **pnodes_p, *pnode = NULL;
3507
3508 /* parse the node */
3509 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, (void **)&pnode, NULL), cleanup);
3510
3511 /* usually is a linked-list of all the parsed schema nodes */
3512 pnodes_p = substmt->storage;
3513 while (*pnodes_p) {
3514 pnodes_p = &(*pnodes_p)->next;
Michal Vasko59892dd2022-05-13 11:02:30 +02003515 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003516 *pnodes_p = pnode;
Michal Vasko59892dd2022-05-13 11:02:30 +02003517
3518 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003519 }
3520 case LY_STMT_BASE:
3521 case LY_STMT_BIT:
3522 case LY_STMT_DEFAULT:
3523 case LY_STMT_DEVIATE:
3524 case LY_STMT_DEVIATION:
3525 case LY_STMT_ENUM:
3526 case LY_STMT_EXTENSION:
3527 case LY_STMT_EXTENSION_INSTANCE:
3528 case LY_STMT_FEATURE:
3529 case LY_STMT_IDENTITY:
3530 case LY_STMT_IF_FEATURE:
3531 case LY_STMT_IMPORT:
3532 case LY_STMT_INCLUDE:
3533 case LY_STMT_MUST:
3534 case LY_STMT_PATTERN:
3535 case LY_STMT_REFINE:
3536 case LY_STMT_REVISION:
3537 case LY_STMT_TYPEDEF:
3538 case LY_STMT_UNIQUE:
3539 /* parse, sized array */
3540 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003541 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003542
3543 case LY_STMT_ARGUMENT:
3544 case LY_STMT_BELONGS_TO:
3545 case LY_STMT_CONTACT:
3546 case LY_STMT_DESCRIPTION:
3547 case LY_STMT_ERROR_APP_TAG:
3548 case LY_STMT_ERROR_MESSAGE:
3549 case LY_STMT_FRACTION_DIGITS:
3550 case LY_STMT_KEY:
3551 case LY_STMT_LENGTH:
3552 case LY_STMT_MANDATORY:
3553 case LY_STMT_MAX_ELEMENTS:
3554 case LY_STMT_MIN_ELEMENTS:
3555 case LY_STMT_MODIFIER:
3556 case LY_STMT_MODULE:
3557 case LY_STMT_NAMESPACE:
3558 case LY_STMT_ORGANIZATION:
3559 case LY_STMT_PATH:
3560 case LY_STMT_POSITION:
3561 case LY_STMT_PREFIX:
3562 case LY_STMT_PRESENCE:
3563 case LY_STMT_RANGE:
3564 case LY_STMT_REFERENCE:
3565 case LY_STMT_REQUIRE_INSTANCE:
3566 case LY_STMT_REVISION_DATE:
3567 case LY_STMT_SUBMODULE:
3568 case LY_STMT_TYPE:
3569 case LY_STMT_UNITS:
3570 case LY_STMT_VALUE:
3571 case LY_STMT_WHEN:
3572 case LY_STMT_YANG_VERSION:
3573 case LY_STMT_YIN_ELEMENT:
3574 /* single item */
3575 if (*(void **)substmt->storage) {
3576 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3577 rc = LY_EVALID;
3578 goto cleanup;
3579 }
3580
3581 /* parse */
3582 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
Michal Vasko59892dd2022-05-13 11:02:30 +02003583 break;
Michal Vasko193dacd2022-10-13 08:43:05 +02003584
3585 case LY_STMT_CONFIG:
3586 /* single item */
3587 if ((*(uint16_t *)substmt->storage) & LYS_CONFIG_MASK) {
3588 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3589 rc = LY_EVALID;
3590 goto cleanup;
3591 }
3592
3593 /* parse */
3594 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3595 break;
3596
3597 case LY_STMT_ORDERED_BY:
3598 /* single item */
3599 if ((*(uint16_t *)substmt->storage) & LYS_ORDBY_MASK) {
3600 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3601 rc = LY_EVALID;
3602 goto cleanup;
3603 }
3604
3605 /* parse */
3606 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3607 break;
3608
3609 case LY_STMT_STATUS:
3610 /* single item */
3611 if ((*(uint16_t *)substmt->storage) & LYS_STATUS_MASK) {
3612 LOGVAL(PARSER_CTX(pctx), LY_VCODE_DUPSTMT, stmt->stmt);
3613 rc = LY_EVALID;
3614 goto cleanup;
3615 }
3616
3617 /* parse */
3618 LY_CHECK_GOTO(rc = lysp_stmt_parse(pctx, stmt, substmt->storage, NULL), cleanup);
3619 break;
3620
Michal Vasko59892dd2022-05-13 11:02:30 +02003621 default:
Michal Vasko193dacd2022-10-13 08:43:05 +02003622 LOGINT(PARSER_CTX(pctx));
3623 rc = LY_EINT;
3624 goto cleanup;
Michal Vasko59892dd2022-05-13 11:02:30 +02003625 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003626
3627cleanup:
3628 return rc;
Michal Vasko59892dd2022-05-13 11:02:30 +02003629}