blob: 79a0f44c8d7a8ffa36a91a8320f3cdc45701fb32 [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"
Radek Krejci77114102021-03-10 15:21:57 +010048#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020049#include "tree.h"
Michal Vasko59892dd2022-05-13 11:02:30 +020050#include "tree_data.h"
51#include "tree_data_internal.h"
Radek Krejci335332a2019-09-05 13:03:35 +020052#include "tree_schema.h"
53#include "tree_schema_internal.h"
54
Michal Vasko59892dd2022-05-13 11:02:30 +020055void
56lyd_ctx_free(struct lyd_ctx *lydctx)
57{
58 ly_set_erase(&lydctx->node_types, NULL);
59 ly_set_erase(&lydctx->meta_types, NULL);
60 ly_set_erase(&lydctx->node_when, NULL);
Michal Vasko135719f2022-08-25 12:18:17 +020061 ly_set_erase(&lydctx->ext_node, free);
Michal Vasko59892dd2022-05-13 11:02:30 +020062 ly_set_erase(&lydctx->ext_val, free);
63}
64
65LY_ERR
66lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op)
67{
68 const struct lyd_node *iter;
69
70 *op = NULL;
71
72 if (!parent) {
73 /* no parent, nothing to look for */
74 return LY_SUCCESS;
75 }
76
77 /* we need to find the operation node if it already exists */
78 for (iter = parent; iter; iter = lyd_parent(iter)) {
79 if (iter->schema && (iter->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
80 break;
81 }
82 }
83
84 if (!iter) {
85 /* no operation found */
86 return LY_SUCCESS;
87 }
88
89 if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY))) {
90 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent %s \"%s\" node when not parsing any operation.",
91 lys_nodetype2str(iter->schema->nodetype), iter->schema->name);
92 return LY_EINVAL;
93 } else if ((iter->schema->nodetype == LYS_RPC) && !(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY))) {
94 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent RPC \"%s\" node when not parsing RPC nor rpc-reply.",
95 iter->schema->name);
96 return LY_EINVAL;
97 } else if ((iter->schema->nodetype == LYS_ACTION) && !(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY))) {
98 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent action \"%s\" node when not parsing action nor rpc-reply.",
99 iter->schema->name);
100 return LY_EINVAL;
101 } else if ((iter->schema->nodetype == LYS_NOTIF) && !(int_opts & LYD_INTOPT_NOTIF)) {
102 LOGERR(LYD_CTX(parent), LY_EINVAL, "Invalid parent notification \"%s\" node when not parsing a notification.",
103 iter->schema->name);
104 return LY_EINVAL;
105 }
106
107 *op = (struct lyd_node *)iter;
108 return LY_SUCCESS;
109}
110
111LY_ERR
112lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
113{
114 LY_ERR rc = LY_SUCCESS;
115
116 LOG_LOCSET(snode, NULL, NULL, NULL);
117
118 if (lydctx->int_opts & LYD_INTOPT_ANY) {
119 /* nothing to check, everything is allowed */
120 goto cleanup;
121 }
122
123 if ((lydctx->parse_opts & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
124 LOGVAL(lydctx->data_ctx->ctx, LY_VCODE_UNEXPNODE, "state", snode->name);
125 rc = LY_EVALID;
126 goto cleanup;
127 }
128
129 if (snode->nodetype == LYS_RPC) {
130 if (lydctx->int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) {
131 if (lydctx->op_node) {
132 goto error_node_dup;
133 }
134 } else {
135 goto error_node_inval;
136 }
137 } else if (snode->nodetype == LYS_ACTION) {
138 if (lydctx->int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
139 if (lydctx->op_node) {
140 goto error_node_dup;
141 }
142 } else {
143 goto error_node_inval;
144 }
145 } else if (snode->nodetype == LYS_NOTIF) {
146 if (lydctx->int_opts & LYD_INTOPT_NOTIF) {
147 if (lydctx->op_node) {
148 goto error_node_dup;
149 }
150 } else {
151 goto error_node_inval;
152 }
153 }
154
155 /* success */
156 goto cleanup;
157
158error_node_dup:
159 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
160 lys_nodetype2str(snode->nodetype), snode->name, lys_nodetype2str(lydctx->op_node->schema->nodetype),
161 lydctx->op_node->schema->name);
162 rc = LY_EVALID;
163 goto cleanup;
164
165error_node_inval:
166 LOGVAL(lydctx->data_ctx->ctx, LYVE_DATA, "Unexpected %s element \"%s\".", lys_nodetype2str(snode->nodetype),
167 snode->name);
168 rc = LY_EVALID;
169
170cleanup:
171 LOG_LOCBACK(1, 0, 0, 0);
172 return rc;
173}
174
175LY_ERR
176lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const void *value, size_t value_len,
177 ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
178{
179 ly_bool incomplete;
180
181 LY_CHECK_RET(lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node));
182
183 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
184 LY_CHECK_RET(ly_set_add(&lydctx->node_types, *node, 1, NULL));
185 }
186 return LY_SUCCESS;
187}
188
189LY_ERR
190lyd_parser_create_meta(struct lyd_ctx *lydctx, struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod,
191 const char *name, size_t name_len, const void *value, size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format,
192 void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node)
193{
194 ly_bool incomplete;
195 struct lyd_meta *first = NULL;
196
197 if (meta && *meta) {
198 /* remember the first metadata */
199 first = *meta;
200 }
201
202 LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
203 hints, ctx_node, 0, &incomplete));
204
205 if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
206 LY_CHECK_RET(ly_set_add(&lydctx->meta_types, *meta, 1, NULL));
207 }
208
209 if (first) {
210 /* always return the first metadata */
211 *meta = first;
212 }
213
214 return LY_SUCCESS;
215}
216
Michal Vasko95c6d5c2022-05-20 10:33:39 +0200217LY_ERR
218lyd_parse_check_keys(struct lyd_node *node)
219{
220 const struct lysc_node *skey = NULL;
221 const struct lyd_node *key;
222
223 assert(node->schema->nodetype == LYS_LIST);
224
225 key = lyd_child(node);
226 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
227 if (!key || (key->schema != skey)) {
228 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
229 return LY_EVALID;
230 }
231
232 key = key->next;
233 }
234
235 return LY_SUCCESS;
236}
237
238LY_ERR
239lyd_parse_set_data_flags(struct lyd_node *node, struct lyd_meta **meta, struct lyd_ctx *lydctx,
240 struct lysc_ext_instance *ext)
241{
242 struct lyd_meta *meta2, *prev_meta = NULL;
243 struct lyd_ctx_ext_val *ext_val;
244
245 if (lysc_has_when(node->schema)) {
246 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
247 /* remember we need to evaluate this node's when */
248 LY_CHECK_RET(ly_set_add(&lydctx->node_when, node, 1, NULL));
249 }
250 }
251
252 LY_LIST_FOR(*meta, meta2) {
253 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
254 meta2->value.boolean) {
255 /* node is default according to the metadata */
256 node->flags |= LYD_DEFAULT;
257
258 /* delete the metadata */
259 if (prev_meta) {
260 prev_meta->next = meta2->next;
261 } else {
262 *meta = (*meta)->next;
263 }
264 lyd_free_meta_single(meta2);
265 break;
266 }
267
268 prev_meta = meta2;
269 }
270
271 if (ext) {
272 /* parsed for an extension */
273 node->flags |= LYD_EXT;
274
275 if (!(lydctx->parse_opts & LYD_PARSE_ONLY)) {
276 /* rememeber for validation */
277 ext_val = malloc(sizeof *ext_val);
278 LY_CHECK_ERR_RET(!ext_val, LOGMEM(LYD_CTX(node)), LY_EMEM);
279 ext_val->ext = ext;
280 ext_val->sibling = node;
281 LY_CHECK_RET(ly_set_add(&lydctx->ext_val, ext_val, 1, NULL));
282 }
283 }
284
285 return LY_SUCCESS;
286}
287
Michal Vaskod0625d72022-10-06 15:02:50 +0200288static 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 +0100289 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200290static 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 +0100291 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200292static 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 +0100293 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200294static 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 +0100295 struct lysp_node **siblings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200296static 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 +0100297 struct lysp_node_grp **groupings);
Michal Vaskod0625d72022-10-06 15:02:50 +0200298static 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 +0100299 struct lysp_node **siblings);
300
Radek Krejci335332a2019-09-05 13:03:35 +0200301static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200302lysp_stmt_validate_value(struct lysp_ctx *ctx, enum yang_arg val_type, const char *val)
Radek Krejci335332a2019-09-05 13:03:35 +0200303{
Radek Krejci857189e2020-09-01 13:26:36 +0200304 uint8_t prefix = 0;
305 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200306 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +0200307 size_t utf8_char_len;
308
309 while (*val) {
310 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200311 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200312
313 switch (val_type) {
314 case Y_IDENTIF_ARG:
315 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
316 break;
317 case Y_PREF_IDENTIF_ARG:
318 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
319 break;
320 case Y_STR_ARG:
321 case Y_MAYBE_STR_ARG:
322 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
323 break;
324 }
325 first = 0;
326 }
327
328 return LY_SUCCESS;
329}
330
331/**
332 * @brief Parse extension instance.
333 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100334 * @param[in] ctx parser context.
335 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejcifc596f92021-02-26 22:40:26 +0100336 * @param[in] insubstmt The statement this extension instance is a substatement of.
Radek Krejci335332a2019-09-05 13:03:35 +0200337 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
338 * @param[in,out] exts Extension instances to add to.
339 *
340 * @return LY_ERR values.
341 */
342static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200343lysp_stmt_ext(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200344 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200345{
346 struct lysp_ext_instance *e;
347
Michal Vaskob36053d2020-03-26 15:49:30 +0100348 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200349
350 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200351 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejciab430862021-03-02 20:13:40 +0100352 e->parent_stmt = insubstmt;
353 e->parent_stmt_index = insubstmt_index;
aPiecek60d9d672021-04-27 15:49:57 +0200354 e->parsed = NULL;
Radek Krejci335332a2019-09-05 13:03:35 +0200355 /* TODO (duplicate) e->child = stmt->child; */
356
357 /* get optional argument */
358 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200359 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +0200360 }
361
362 return LY_SUCCESS;
363}
364
365/**
366 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
367 * description, etc...
368 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100369 * @param[in] ctx parser context.
370 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200371 * @param[in] substmt_index Index of this substatement.
372 * @param[in,out] value Place to store the parsed value.
373 * @param[in] arg Type of the YANG keyword argument (of the value).
374 * @param[in,out] exts Extension instances to add to.
375 *
376 * @return LY_ERR values.
377 */
378static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200379lysp_stmt_text_field(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint32_t substmt_index,
Radek Krejci0f969882020-08-21 16:56:47 +0200380 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200381{
Radek Krejci335332a2019-09-05 13:03:35 +0200382 if (*value) {
Radek Krejci3972b332021-03-02 16:34:31 +0100383 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200384 return LY_EVALID;
385 }
386
387 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200388 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200389
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100390 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
391 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200392 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100393 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, substmt_index, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200394 break;
395 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100396 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200397 return LY_EVALID;
398 }
399 }
400 return LY_SUCCESS;
401}
402
403/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200404 * @brief Parse a qname that can have more instances such as if-feature.
405 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100406 * @param[in] ctx parser context.
407 * @param[in] stmt Source statement data from the parsed extension instance.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200408 * @param[in,out] qnames Parsed qnames to add to.
409 * @param[in] arg Type of the expected argument.
410 * @param[in,out] exts Extension instances to add to.
411 *
412 * @return LY_ERR values.
413 */
414static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200415lysp_stmt_qnames(struct lysp_ctx *ctx, const struct lysp_stmt *stmt,
Michal Vasko7f45cf22020-10-01 12:49:44 +0200416 struct lysp_qname **qnames, enum yang_arg arg, struct lysp_ext_instance **exts)
417{
418 struct lysp_qname *item;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200419
420 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
421
422 /* allocate new pointer */
423 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
424 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100425 item->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200426
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100427 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
428 switch (child->kw) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200429 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100430 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200431 break;
432 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100433 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200434 return LY_EVALID;
435 }
436 }
437 return LY_SUCCESS;
438}
439
440/**
Radek Krejci335332a2019-09-05 13:03:35 +0200441 * @brief Parse a generic text field that can have more instances such as base.
442 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100443 * @param[in] ctx parser context.
444 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200445 * @param[in,out] texts Parsed values to add to.
446 * @param[in] arg Type of the expected argument.
447 * @param[in,out] exts Extension instances to add to.
448 *
449 * @return LY_ERR values.
450 */
451static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200452lysp_stmt_text_fields(struct lysp_ctx *ctx, const struct lysp_stmt *stmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200453 const char ***texts, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200454{
455 const char **item;
Radek Krejci335332a2019-09-05 13:03:35 +0200456
457 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
458
459 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100460 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200461 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200462
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100463 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
464 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200465 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100466 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200467 break;
468 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100469 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200470 return LY_EVALID;
471 }
472 }
473 return LY_SUCCESS;
474}
475
476/**
477 * @brief Parse the status statement.
478 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100479 * @param[in] ctx parser context.
480 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200481 * @param[in,out] flags Flags to add to.
482 * @param[in,out] exts Extension instances to add to.
483 *
484 * @return LY_ERR values.
485 */
486static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200487lysp_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 +0200488{
489 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200490
491 if (*flags & LYS_STATUS_MASK) {
492 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
493 return LY_EVALID;
494 }
495
496 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
497 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100498 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200499 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100500 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200501 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100502 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200503 *flags |= LYS_STATUS_OBSLT;
504 } else {
505 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
506 return LY_EVALID;
507 }
508
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100509 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
510 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200511 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100512 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_STATUS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200513 break;
514 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100515 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "status");
Radek Krejci335332a2019-09-05 13:03:35 +0200516 return LY_EVALID;
517 }
518 }
519 return LY_SUCCESS;
520}
521
522/**
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100523 * @brief Parse the when statement.
Radek Krejci335332a2019-09-05 13:03:35 +0200524 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100525 * @param[in] ctx parser context.
526 * @param[in] stmt Source statement data from the parsed extension instance.
527 * @param[in,out] when_p When pointer to parse to.
528 *
529 * @return LY_ERR values.
530 */
531static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200532lysp_stmt_when(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_when **when_p)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100533{
534 LY_ERR ret = LY_SUCCESS;
535 struct lysp_when *when;
536
537 if (*when_p) {
538 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
539 return LY_EVALID;
540 }
541
542 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
543
544 when = calloc(1, sizeof *when);
545 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
546 *when_p = when;
547
548 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &when->cond));
549
550 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
551 switch (child->kw) {
552 case LY_STMT_DESCRIPTION:
553 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->dsc, Y_STR_ARG, &when->exts));
554 break;
555 case LY_STMT_REFERENCE:
556 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &when->ref, Y_STR_ARG, &when->exts));
557 break;
558 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100559 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_WHEN, 0, &when->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100560 break;
561 default:
562 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "when");
563 return LY_EVALID;
564 }
565 }
566 return ret;
567}
568
569/**
570 * @brief Parse the config statement.
571 *
572 * @param[in] ctx parser context.
573 * @param[in] stmt Source statement data from the parsed extension instance.
574 * @param[in,out] flags Flags to add to.
Radek Krejci335332a2019-09-05 13:03:35 +0200575 * @param[in,out] exts Extension instances to add to.
576 *
577 * @return LY_ERR values.
578 */
579static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200580lysp_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 +0200581{
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100582 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200583
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100584 if (*flags & LYS_CONFIG_MASK) {
585 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
586 return LY_EVALID;
587 }
588
589 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
590 arg_len = strlen(stmt->arg);
591 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
592 *flags |= LYS_CONFIG_W;
593 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
594 *flags |= LYS_CONFIG_R;
595 } else {
596 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "config");
597 return LY_EVALID;
598 }
599
600 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
601 switch (child->kw) {
602 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100603 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONFIG, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100604 break;
605 default:
606 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "config");
607 return LY_EVALID;
608 }
609 }
610
611 return LY_SUCCESS;
612}
613
614/**
615 * @brief Parse the mandatory statement.
616 *
617 * @param[in] ctx parser context.
618 * @param[in] stmt Source statement data from the parsed extension instance.
619 * @param[in,out] flags Flags to add to.
620 * @param[in,out] exts Extension instances to add to.
621 *
622 * @return LY_ERR values.
623 */
624static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200625lysp_stmt_mandatory(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags,
Michal Vasko59892dd2022-05-13 11:02:30 +0200626 struct lysp_ext_instance **exts)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100627{
628 size_t arg_len;
629
630 if (*flags & LYS_MAND_MASK) {
631 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
632 return LY_EVALID;
633 }
634
635 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
636 arg_len = strlen(stmt->arg);
637 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
638 *flags |= LYS_MAND_TRUE;
639 } else if ((arg_len == ly_strlen_const("false")) && !strncmp(stmt->arg, "false", arg_len)) {
640 *flags |= LYS_MAND_FALSE;
641 } else {
642 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "mandatory");
643 return LY_EVALID;
644 }
645
646 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
647 switch (child->kw) {
648 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100649 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MANDATORY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100650 break;
651 default:
652 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "mandatory");
653 return LY_EVALID;
654 }
655 }
656
657 return LY_SUCCESS;
658}
659
660/**
661 * @brief Parse a restriction such as range or length.
662 *
663 * @param[in] ctx parser context.
664 * @param[in] stmt Source statement data from the parsed extension instance.
665 * @param[in,out] exts Extension instances to add to.
666 *
667 * @return LY_ERR values.
668 */
669static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200670lysp_stmt_restr(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr *restr)
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100671{
Radek Krejci335332a2019-09-05 13:03:35 +0200672 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200673 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100674 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +0200675
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100676 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
677 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200678 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100679 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200680 break;
681 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100682 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200683 break;
684 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100685 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200686 break;
687 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100688 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200689 break;
690 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100691 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200692 break;
693 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100694 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200695 return LY_EVALID;
696 }
697 }
698 return LY_SUCCESS;
699}
700
701/**
702 * @brief Parse a restriction that can have more instances such as must.
703 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100704 * @param[in] ctx parser context.
705 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200706 * @param[in,out] restrs Restrictions to add to.
707 *
708 * @return LY_ERR values.
709 */
710static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200711lysp_stmt_restrs(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **restrs)
Radek Krejci335332a2019-09-05 13:03:35 +0200712{
713 struct lysp_restr *restr;
714
Michal Vaskob36053d2020-03-26 15:49:30 +0100715 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100716 return lysp_stmt_restr(ctx, stmt, restr);
717}
718
719/**
720 * @brief Parse the anydata or anyxml statement.
721 *
722 * @param[in] ctx parser context.
723 * @param[in] stmt Source statement data from the parsed extension instance.
724 * @param[in,out] siblings Siblings to add to.
725 *
726 * @return LY_ERR values.
727 */
728static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200729lysp_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 +0100730{
731 struct lysp_node_anydata *any;
732
733 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
734
735 /* create new structure and insert into siblings */
736 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
737
738 any->nodetype = stmt->kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
739 any->parent = parent;
740
741 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &any->name));
742
743 /* parse substatements */
744 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
745 switch (child->kw) {
746 case LY_STMT_CONFIG:
747 LY_CHECK_RET(lysp_stmt_config(ctx, child, &any->flags, &any->exts));
748 break;
749 case LY_STMT_DESCRIPTION:
750 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->dsc, Y_STR_ARG, &any->exts));
751 break;
752 case LY_STMT_IF_FEATURE:
753 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &any->iffeatures, Y_STR_ARG, &any->exts));
754 break;
755 case LY_STMT_MANDATORY:
756 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &any->flags, &any->exts));
757 break;
758 case LY_STMT_MUST:
759 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &any->musts));
760 break;
761 case LY_STMT_REFERENCE:
762 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &any->ref, Y_STR_ARG, &any->exts));
763 break;
764 case LY_STMT_STATUS:
765 LY_CHECK_RET(lysp_stmt_status(ctx, child, &any->flags, &any->exts));
766 break;
767 case LY_STMT_WHEN:
768 LY_CHECK_RET(lysp_stmt_when(ctx, child, &any->when));
769 break;
770 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100771 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &any->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100772 break;
773 default:
774 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
775 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(LY_STMT_ANYDATA) : ly_stmt2str(LY_STMT_ANYXML));
776 return LY_EVALID;
777 }
778 }
779
780 return LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200781}
782
783/**
784 * @brief Parse the value or position statement. Substatement of type enum statement.
785 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100786 * @param[in] ctx parser context.
787 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200788 * @param[in,out] value Value to write to.
789 * @param[in,out] flags Flags to write to.
790 * @param[in,out] exts Extension instances to add to.
791 *
792 * @return LY_ERR values.
793 */
794static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200795lysp_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 +0200796 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200797{
798 size_t arg_len;
799 char *ptr = NULL;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200800 long long int num = 0;
801 unsigned long long int unum = 0;
Radek Krejci335332a2019-09-05 13:03:35 +0200802
803 if (*flags & LYS_SET_VALUE) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100804 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200805 return LY_EVALID;
806 }
807 *flags |= LYS_SET_VALUE;
808
809 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
810
811 arg_len = strlen(stmt->arg);
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100812 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) ||
813 ((stmt->kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
814 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200815 goto error;
816 }
817
818 errno = 0;
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100819 if (stmt->kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200820 num = strtoll(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200821 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100822 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200823 goto error;
824 }
825 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +0200826 unum = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200827 if (unum > UINT64_C(4294967295)) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100828 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200829 goto error;
830 }
831 }
832 /* we have not parsed the whole argument */
833 if ((size_t)(ptr - stmt->arg) != arg_len) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100834 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200835 goto error;
836 }
837 if (errno == ERANGE) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100838 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200839 goto error;
840 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100841 if (stmt->kw == LY_STMT_VALUE) {
Radek Krejci335332a2019-09-05 13:03:35 +0200842 *value = num;
843 } else {
844 *value = unum;
845 }
846
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100847 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
848 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200849 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100850 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 +0200851 break;
852 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100853 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200854 return LY_EVALID;
855 }
856 }
857 return LY_SUCCESS;
858
859error:
860 return LY_EVALID;
861}
862
863/**
864 * @brief Parse the enum or bit statement. Substatement of type statement.
865 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100866 * @param[in] ctx parser context.
867 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200868 * @param[in,out] enums Enums or bits to add to.
869 *
870 * @return LY_ERR values.
871 */
872static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200873lysp_stmt_type_enum(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type_enum **enums)
Radek Krejci335332a2019-09-05 13:03:35 +0200874{
875 struct lysp_type_enum *enm;
Radek Krejci335332a2019-09-05 13:03:35 +0200876
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100877 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 +0200878
Michal Vaskob36053d2020-03-26 15:49:30 +0100879 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200880
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100881 if (stmt->kw == LY_STMT_ENUM) {
Radek Krejci335332a2019-09-05 13:03:35 +0200882 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
883 } /* else nothing specific for YANG_BIT */
884
Radek Krejci011e4aa2020-09-04 15:22:31 +0200885 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100886 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(stmt->kw), enm->name);
Radek Krejci335332a2019-09-05 13:03:35 +0200887
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100888 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
889 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200890 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100891 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200892 break;
893 case LY_STMT_IF_FEATURE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100894 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(stmt->kw));
895 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200896 break;
897 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100898 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200899 break;
900 case LY_STMT_STATUS:
901 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
902 break;
903 case LY_STMT_VALUE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100904 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
905 ly_stmt2str(stmt->kw)), LY_EVALID);
906 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200907 break;
908 case LY_STMT_POSITION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100909 LY_CHECK_ERR_RET(stmt->kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw),
910 ly_stmt2str(stmt->kw)), LY_EVALID);
911 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, &enm->value, &enm->flags, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200912 break;
913 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +0100914 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200915 break;
916 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100917 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
Radek Krejci335332a2019-09-05 13:03:35 +0200918 return LY_EVALID;
919 }
920 }
921 return LY_SUCCESS;
922}
923
924/**
925 * @brief Parse the fraction-digits statement. Substatement of type statement.
926 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100927 * @param[in] ctx parser context.
928 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200929 * @param[in,out] fracdig Value to write to.
930 * @param[in,out] exts Extension instances to add to.
931 *
932 * @return LY_ERR values.
933 */
934static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200935lysp_stmt_type_fracdigits(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig,
Michal Vasko59892dd2022-05-13 11:02:30 +0200936 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200937{
938 char *ptr;
939 size_t arg_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200940 unsigned long long int num;
Radek Krejci335332a2019-09-05 13:03:35 +0200941
942 if (*fracdig) {
943 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
944 return LY_EVALID;
945 }
946
947 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
948 arg_len = strlen(stmt->arg);
949 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
950 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
951 return LY_EVALID;
952 }
953
954 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200955 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200956 /* we have not parsed the whole argument */
957 if ((size_t)(ptr - stmt->arg) != arg_len) {
958 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
959 return LY_EVALID;
960 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100961 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200962 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
963 return LY_EVALID;
964 }
965 *fracdig = num;
966
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100967 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
968 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +0200969 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +0100970 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200971 break;
972 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100973 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "fraction-digits");
Radek Krejci335332a2019-09-05 13:03:35 +0200974 return LY_EVALID;
975 }
976 }
977 return LY_SUCCESS;
978}
979
980/**
981 * @brief Parse the require-instance statement. Substatement of type statement.
982 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +0100983 * @param[in] ctx parser context.
984 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +0200985 * @param[in,out] reqinst Value to write to.
986 * @param[in,out] flags Flags to write to.
987 * @param[in,out] exts Extension instances to add to.
988 *
989 * @return LY_ERR values.
990 */
991static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200992lysp_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 +0200993 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200994{
995 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +0200996
997 if (*flags & LYS_SET_REQINST) {
998 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
999 return LY_EVALID;
1000 }
1001 *flags |= LYS_SET_REQINST;
1002
1003 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1004 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001005 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001006 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001007 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001008 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
1009 return LY_EVALID;
1010 }
1011
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001012 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1013 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001014 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001015 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001016 break;
1017 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001018 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "require-instance");
Radek Krejci335332a2019-09-05 13:03:35 +02001019 return LY_EVALID;
1020 }
1021 }
1022 return LY_SUCCESS;
1023}
1024
1025/**
1026 * @brief Parse the modifier statement. Substatement of type pattern statement.
1027 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001028 * @param[in] ctx parser context.
1029 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001030 * @param[in,out] pat Value to write to.
1031 * @param[in,out] exts Extension instances to add to.
1032 *
1033 * @return LY_ERR values.
1034 */
1035static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001036lysp_stmt_type_pattern_modifier(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, const char **pat,
Michal Vasko59892dd2022-05-13 11:02:30 +02001037 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02001038{
1039 size_t arg_len;
1040 char *buf;
Radek Krejci335332a2019-09-05 13:03:35 +02001041
Radek Krejcif13b87b2020-12-01 22:02:17 +01001042 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +02001043 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
1044 return LY_EVALID;
1045 }
1046
1047 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1048 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001049 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +02001050 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
1051 return LY_EVALID;
1052 }
1053
1054 /* replace the value in the dictionary */
1055 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +01001056 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001057 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +01001058 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +02001059
Radek Krejcif13b87b2020-12-01 22:02:17 +01001060 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1061 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001062 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +02001063
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001064 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1065 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001066 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001067 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MODIFIER, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001068 break;
1069 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001070 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "modifier");
Radek Krejci335332a2019-09-05 13:03:35 +02001071 return LY_EVALID;
1072 }
1073 }
1074 return LY_SUCCESS;
1075}
1076
1077/**
1078 * @brief Parse the pattern statement. Substatement of type statement.
1079 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001080 * @param[in] ctx parser context.
1081 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001082 * @param[in,out] patterns Restrictions to add to.
1083 *
1084 * @return LY_ERR values.
1085 */
1086static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001087lysp_stmt_type_pattern(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
Radek Krejci335332a2019-09-05 13:03:35 +02001088{
1089 char *buf;
1090 size_t arg_len;
Radek Krejci335332a2019-09-05 13:03:35 +02001091 struct lysp_restr *restr;
1092
1093 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +01001094 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001095 arg_len = strlen(stmt->arg);
1096
1097 /* add special meaning first byte */
1098 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +01001099 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001100 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001101 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +02001102 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001103 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001104 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001105
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001106 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1107 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001108 case LY_STMT_DESCRIPTION:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001109 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001110 break;
1111 case LY_STMT_REFERENCE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001112 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001113 break;
1114 case LY_STMT_ERROR_APP_TAG:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001115 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001116 break;
1117 case LY_STMT_ERROR_MESSAGE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001118 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001119 break;
1120 case LY_STMT_MODIFIER:
1121 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02001122 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001123 break;
1124 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001125 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_PATTERN, 0, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001126 break;
1127 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001128 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "pattern");
Radek Krejci335332a2019-09-05 13:03:35 +02001129 return LY_EVALID;
1130 }
1131 }
1132 return LY_SUCCESS;
1133}
1134
1135/**
1136 * @brief Parse the type statement.
1137 *
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001138 * @param[in] ctx parser context.
1139 * @param[in] stmt Source statement data from the parsed extension instance.
Radek Krejci335332a2019-09-05 13:03:35 +02001140 * @param[in,out] type Type to wrote to.
1141 *
1142 * @return LY_ERR values.
1143 */
1144static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001145lysp_stmt_type(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
Radek Krejci335332a2019-09-05 13:03:35 +02001146{
1147 struct lysp_type *nest_type;
Radek Krejcib1247842020-07-02 16:22:38 +02001148 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +02001149 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +02001150
1151 if (type->name) {
1152 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
1153 return LY_EVALID;
1154 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001155
1156 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001157 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001158 type->pmod = PARSER_CUR_PMOD(ctx);
Radek Krejci335332a2019-09-05 13:03:35 +02001159
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001160 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1161 switch (child->kw) {
Radek Krejci335332a2019-09-05 13:03:35 +02001162 case LY_STMT_BASE:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001163 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001164 type->flags |= LYS_SET_BASE;
1165 break;
1166 case LY_STMT_BIT:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001167 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->bits));
Radek Krejci335332a2019-09-05 13:03:35 +02001168 type->flags |= LYS_SET_BIT;
1169 break;
1170 case LY_STMT_ENUM:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001171 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, &type->enums));
Radek Krejci335332a2019-09-05 13:03:35 +02001172 type->flags |= LYS_SET_ENUM;
1173 break;
1174 case LY_STMT_FRACTION_DIGITS:
1175 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
1176 type->flags |= LYS_SET_FRDIGITS;
1177 break;
1178 case LY_STMT_LENGTH:
1179 if (type->length) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001180 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001181 return LY_EVALID;
1182 }
1183 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001184 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001185
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001186 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->length));
Radek Krejci335332a2019-09-05 13:03:35 +02001187 type->flags |= LYS_SET_LENGTH;
1188 break;
1189 case LY_STMT_PATH:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001190 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02001191 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02001192 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +02001193 lydict_remove(PARSER_CTX(ctx), str_path);
1194 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001195 type->flags |= LYS_SET_PATH;
1196 break;
1197 case LY_STMT_PATTERN:
1198 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
1199 type->flags |= LYS_SET_PATTERN;
1200 break;
1201 case LY_STMT_RANGE:
1202 if (type->range) {
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001203 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(child->kw));
Radek Krejci335332a2019-09-05 13:03:35 +02001204 return LY_EVALID;
1205 }
1206 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001207 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001208
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001209 LY_CHECK_RET(lysp_stmt_restr(ctx, child, type->range));
Radek Krejci335332a2019-09-05 13:03:35 +02001210 type->flags |= LYS_SET_RANGE;
1211 break;
1212 case LY_STMT_REQUIRE_INSTANCE:
1213 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001214 /* LYS_SET_REQINST checked and set inside lysp_stmt_type_reqinstance() */
Radek Krejci335332a2019-09-05 13:03:35 +02001215 break;
1216 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +01001217 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +02001218 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
1219 type->flags |= LYS_SET_TYPE;
1220 break;
1221 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001222 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPE, 0, &type->exts));
Radek Krejci335332a2019-09-05 13:03:35 +02001223 break;
1224 default:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001225 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "type");
Radek Krejci335332a2019-09-05 13:03:35 +02001226 return LY_EVALID;
1227 }
1228 }
1229 return LY_SUCCESS;
1230}
1231
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001232/**
1233 * @brief Parse the leaf statement.
1234 *
1235 * @param[in] ctx parser context.
1236 * @param[in] stmt Source statement data from the parsed extension instance.
1237 * @param[in] parent Parent node to connect to (not into).
1238 * @param[in,out] siblings Siblings to add to.
1239 *
1240 * @return LY_ERR values.
1241 */
1242static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001243lysp_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 +01001244{
1245 struct lysp_node_leaf *leaf;
1246
1247 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1248
1249 /* create new leaf structure */
1250 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
1251 leaf->nodetype = LYS_LEAF;
1252 leaf->parent = parent;
1253
1254 /* get name */
1255 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &leaf->name));
1256
1257 /* parse substatements */
1258 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1259 switch (child->kw) {
1260 case LY_STMT_CONFIG:
1261 LY_CHECK_RET(lysp_stmt_config(ctx, child, &leaf->flags, &leaf->exts));
1262 break;
1263 case LY_STMT_DEFAULT:
1264 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 +01001265 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001266 break;
1267 case LY_STMT_DESCRIPTION:
1268 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
1269 break;
1270 case LY_STMT_IF_FEATURE:
1271 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
1272 break;
1273 case LY_STMT_MANDATORY:
1274 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &leaf->flags, &leaf->exts));
1275 break;
1276 case LY_STMT_MUST:
1277 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &leaf->musts));
1278 break;
1279 case LY_STMT_REFERENCE:
1280 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
1281 break;
1282 case LY_STMT_STATUS:
1283 LY_CHECK_RET(lysp_stmt_status(ctx, child, &leaf->flags, &leaf->exts));
1284 break;
1285 case LY_STMT_TYPE:
1286 LY_CHECK_RET(lysp_stmt_type(ctx, child, &leaf->type));
1287 break;
1288 case LY_STMT_UNITS:
1289 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
1290 break;
1291 case LY_STMT_WHEN:
1292 LY_CHECK_RET(lysp_stmt_when(ctx, child, &leaf->when));
1293 break;
1294 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001295 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF, 0, &leaf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001296 break;
1297 default:
1298 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "leaf");
1299 return LY_EVALID;
1300 }
1301 }
1302
1303 /* mandatory substatements */
1304 if (!leaf->type.name) {
1305 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
1306 return LY_EVALID;
1307 }
1308
1309 return LY_SUCCESS;
1310}
1311
1312/**
1313 * @brief Parse the max-elements statement.
1314 *
1315 * @param[in] ctx parser context.
1316 * @param[in] stmt Source statement data from the parsed extension instance.
1317 * @param[in,out] max Value to write to.
1318 * @param[in,out] flags Flags to write to.
1319 * @param[in,out] exts Extension instances to add to.
1320 *
1321 * @return LY_ERR values.
1322 */
1323static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001324lysp_stmt_maxelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001325 uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
1326{
1327 size_t arg_len;
1328 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001329 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001330
1331 if (*flags & LYS_SET_MAX) {
1332 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
1333 return LY_EVALID;
1334 }
1335 *flags |= LYS_SET_MAX;
1336
1337 /* get value */
1338 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1339 arg_len = strlen(stmt->arg);
1340
1341 if (!arg_len || (stmt->arg[0] == '0') || ((stmt->arg[0] != 'u') && !isdigit(stmt->arg[0]))) {
1342 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1343 return LY_EVALID;
1344 }
1345
1346 if ((arg_len != ly_strlen_const("unbounded")) || strncmp(stmt->arg, "unbounded", arg_len)) {
1347 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001348 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001349 /* we have not parsed the whole argument */
1350 if ((size_t)(ptr - stmt->arg) != arg_len) {
1351 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "max-elements");
1352 return LY_EVALID;
1353 }
1354 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1355 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "max-elements");
1356 return LY_EVALID;
1357 }
1358
1359 *max = num;
1360 } else {
1361 /* unbounded */
1362 *max = 0;
1363 }
1364
1365 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1366 switch (child->kw) {
1367 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001368 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MAX_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001369 break;
1370 default:
1371 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "max-elements");
1372 return LY_EVALID;
1373 }
1374 }
1375
1376 return LY_SUCCESS;
1377}
1378
1379/**
1380 * @brief Parse the min-elements statement.
1381 *
1382 * @param[in] ctx parser context.
1383 * @param[in] stmt Source statement data from the parsed extension instance.
1384 * @param[in,out] min Value to write to.
1385 * @param[in,out] flags Flags to write to.
1386 * @param[in,out] exts Extension instances to add to.
1387 *
1388 * @return LY_ERR values.
1389 */
1390static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001391lysp_stmt_minelements(struct lysp_ctx *ctx, const struct lysp_stmt *stmt,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001392 uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
1393{
1394 size_t arg_len;
1395 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001396 unsigned long long int num;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001397
1398 if (*flags & LYS_SET_MIN) {
1399 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
1400 return LY_EVALID;
1401 }
1402 *flags |= LYS_SET_MIN;
1403
1404 /* get value */
1405 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1406 arg_len = strlen(stmt->arg);
1407
1408 if (!arg_len || !isdigit(stmt->arg[0]) || ((stmt->arg[0] == '0') && (arg_len > 1))) {
1409 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1410 return LY_EVALID;
1411 }
1412
1413 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001414 num = strtoull(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001415 /* we have not parsed the whole argument */
1416 if ((size_t)(ptr - stmt->arg) != arg_len) {
1417 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "min-elements");
1418 return LY_EVALID;
1419 }
1420 if ((errno == ERANGE) || (num > UINT32_MAX)) {
1421 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "min-elements");
1422 return LY_EVALID;
1423 }
1424 *min = num;
1425
1426 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1427 switch (child->kw) {
1428 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001429 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_MIN_ELEMENTS, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001430 break;
1431 default:
1432 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "min-elements");
1433 return LY_EVALID;
1434 }
1435 }
1436
1437 return LY_SUCCESS;
1438}
1439
1440/**
1441 * @brief Parse the ordered-by statement.
1442 *
1443 * @param[in] ctx parser context.
1444 * @param[in] stmt Source statement data from the parsed extension instance.
1445 * @param[in,out] flags Flags to write to.
1446 * @param[in,out] exts Extension instances to add to.
1447 *
1448 * @return LY_ERR values.
1449 */
1450static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001451lysp_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 +01001452{
1453 size_t arg_len;
1454
1455 if (*flags & LYS_ORDBY_MASK) {
1456 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
1457 return LY_EVALID;
1458 }
1459
1460 /* get value */
1461 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1462 arg_len = strlen(stmt->arg);
1463 if ((arg_len == ly_strlen_const("system")) && !strncmp(stmt->arg, "system", arg_len)) {
1464 *flags |= LYS_MAND_TRUE;
1465 } else if ((arg_len == ly_strlen_const("user")) && !strncmp(stmt->arg, "user", arg_len)) {
1466 *flags |= LYS_MAND_FALSE;
1467 } else {
1468 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "ordered-by");
1469 return LY_EVALID;
1470 }
1471
1472 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1473 switch (child->kw) {
1474 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001475 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_ORDERED_BY, 0, exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001476 break;
1477 default:
1478 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "ordered-by");
1479 return LY_EVALID;
1480 }
1481 }
1482
1483 return LY_SUCCESS;
1484}
1485
1486/**
1487 * @brief Parse the leaf-list statement.
1488 *
1489 * @param[in] ctx parser context.
1490 * @param[in] stmt Source statement data from the parsed extension instance.
1491 * @param[in] parent Parent node to connect to (not into).
1492 * @param[in,out] siblings Siblings to add to.
1493 *
1494 * @return LY_ERR values.
1495 */
1496static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001497lysp_stmt_leaflist(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02001498 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001499{
1500 struct lysp_node_leaflist *llist;
1501
1502 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1503
1504 /* create new leaf-list structure */
1505 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
1506 llist->nodetype = LYS_LEAFLIST;
1507 llist->parent = parent;
1508
1509 /* get name */
1510 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &llist->name));
1511
1512 /* parse substatements */
1513 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1514 switch (child->kw) {
1515 case LY_STMT_CONFIG:
1516 LY_CHECK_RET(lysp_stmt_config(ctx, child, &llist->flags, &llist->exts));
1517 break;
1518 case LY_STMT_DEFAULT:
1519 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
1520 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->dflts, Y_STR_ARG, &llist->exts));
1521 break;
1522 case LY_STMT_DESCRIPTION:
1523 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
1524 break;
1525 case LY_STMT_IF_FEATURE:
1526 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &llist->iffeatures, Y_STR_ARG, &llist->exts));
1527 break;
1528 case LY_STMT_MAX_ELEMENTS:
1529 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &llist->max, &llist->flags, &llist->exts));
1530 break;
1531 case LY_STMT_MIN_ELEMENTS:
1532 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &llist->min, &llist->flags, &llist->exts));
1533 break;
1534 case LY_STMT_MUST:
1535 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &llist->musts));
1536 break;
1537 case LY_STMT_ORDERED_BY:
1538 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &llist->flags, &llist->exts));
1539 break;
1540 case LY_STMT_REFERENCE:
1541 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->ref, Y_STR_ARG, &llist->exts));
1542 break;
1543 case LY_STMT_STATUS:
1544 LY_CHECK_RET(lysp_stmt_status(ctx, child, &llist->flags, &llist->exts));
1545 break;
1546 case LY_STMT_TYPE:
1547 LY_CHECK_RET(lysp_stmt_type(ctx, child, &llist->type));
1548 break;
1549 case LY_STMT_UNITS:
1550 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &llist->units, Y_STR_ARG, &llist->exts));
1551 break;
1552 case LY_STMT_WHEN:
1553 LY_CHECK_RET(lysp_stmt_when(ctx, child, &llist->when));
1554 break;
1555 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001556 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LEAF_LIST, 0, &llist->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001557 break;
1558 default:
1559 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "llist");
1560 return LY_EVALID;
1561 }
1562 }
1563
1564 /* mandatory substatements */
1565 if (!llist->type.name) {
1566 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
1567 return LY_EVALID;
1568 }
1569
1570 return LY_SUCCESS;
1571}
1572
1573/**
1574 * @brief Parse the refine statement.
1575 *
1576 * @param[in] ctx parser context.
1577 * @param[in] stmt Source statement data from the parsed extension instance.
1578 * @param[in,out] refines Refines to add to.
1579 *
1580 * @return LY_ERR values.
1581 */
1582static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001583lysp_stmt_refine(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_refine **refines)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001584{
1585 struct lysp_refine *rf;
1586
1587 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
1588
1589 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
1590
1591 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &rf->nodeid));
1592
1593 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1594 switch (child->kw) {
1595 case LY_STMT_CONFIG:
1596 LY_CHECK_RET(lysp_stmt_config(ctx, child, &rf->flags, &rf->exts));
1597 break;
1598 case LY_STMT_DEFAULT:
1599 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->dflts, Y_STR_ARG, &rf->exts));
1600 break;
1601 case LY_STMT_DESCRIPTION:
1602 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
1603 break;
1604 case LY_STMT_IF_FEATURE:
1605 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
1606 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &rf->iffeatures, Y_STR_ARG, &rf->exts));
1607 break;
1608 case LY_STMT_MAX_ELEMENTS:
1609 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &rf->max, &rf->flags, &rf->exts));
1610 break;
1611 case LY_STMT_MIN_ELEMENTS:
1612 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &rf->min, &rf->flags, &rf->exts));
1613 break;
1614 case LY_STMT_MUST:
1615 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &rf->musts));
1616 break;
1617 case LY_STMT_MANDATORY:
1618 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &rf->flags, &rf->exts));
1619 break;
1620 case LY_STMT_REFERENCE:
1621 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->ref, Y_STR_ARG, &rf->exts));
1622 break;
1623 case LY_STMT_PRESENCE:
1624 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &rf->presence, Y_STR_ARG, &rf->exts));
1625 break;
1626 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001627 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_REFINE, 0, &rf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001628 break;
1629 default:
1630 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "refine");
1631 return LY_EVALID;
1632 }
1633 }
1634
1635 return LY_SUCCESS;
1636}
1637
1638/**
1639 * @brief Parse the typedef statement.
1640 *
1641 * @param[in] ctx parser context.
1642 * @param[in] stmt Source statement data from the parsed extension instance.
1643 * @param[in] parent Parent node to connect to (not into).
1644 * @param[in,out] typedefs Typedefs to add to.
1645 *
1646 * @return LY_ERR values.
1647 */
1648static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001649lysp_stmt_typedef(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02001650 struct lysp_tpdf **typedefs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001651{
1652 struct lysp_tpdf *tpdf;
1653
1654 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1655
1656 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
1657
1658 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &tpdf->name));
1659
1660 /* parse substatements */
1661 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1662 switch (child->kw) {
1663 case LY_STMT_DEFAULT:
1664 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 +01001665 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001666 break;
1667 case LY_STMT_DESCRIPTION:
1668 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
1669 break;
1670 case LY_STMT_REFERENCE:
1671 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
1672 break;
1673 case LY_STMT_STATUS:
1674 LY_CHECK_RET(lysp_stmt_status(ctx, child, &tpdf->flags, &tpdf->exts));
1675 break;
1676 case LY_STMT_TYPE:
1677 LY_CHECK_RET(lysp_stmt_type(ctx, child, &tpdf->type));
1678 break;
1679 case LY_STMT_UNITS:
1680 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
1681 break;
1682 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001683 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001684 break;
1685 default:
1686 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "typedef");
1687 return LY_EVALID;
1688 }
1689 }
1690
1691 /* mandatory substatements */
1692 if (!tpdf->type.name) {
1693 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
1694 return LY_EVALID;
1695 }
1696
1697 /* store data for collision check */
1698 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
1699 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
1700 }
1701
1702 return LY_SUCCESS;
1703}
1704
1705/**
1706 * @brief Parse the input or output statement.
1707 *
1708 * @param[in] ctx parser context.
1709 * @param[in] stmt Source statement data from the parsed extension instance.
1710 * @param[in] parent Parent node to connect to (not into).
1711 * @param[in,out] inout_p Input/output pointer to write to.
1712 *
1713 * @return LY_ERR values.
1714 */
1715static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001716lysp_stmt_inout(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001717 struct lysp_node_action_inout *inout_p)
1718{
1719 if (inout_p->nodetype) {
1720 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(stmt->kw));
1721 return LY_EVALID;
1722 }
1723
1724 /* initiate structure */
1725 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->kw == LY_STMT_INPUT ? "input" : "output", 0, &inout_p->name));
1726 inout_p->nodetype = stmt->kw == LY_STMT_INPUT ? LYS_INPUT : LYS_OUTPUT;
1727 inout_p->parent = parent;
1728
1729 /* parse substatements */
1730 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1731 switch (child->kw) {
1732 case LY_STMT_ANYDATA:
1733 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(stmt->kw));
1734 /* fall through */
1735 case LY_STMT_ANYXML:
1736 LY_CHECK_RET(lysp_stmt_any(ctx, child, &inout_p->node, &inout_p->child));
1737 break;
1738 case LY_STMT_CHOICE:
1739 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &inout_p->node, &inout_p->child));
1740 break;
1741 case LY_STMT_CONTAINER:
1742 LY_CHECK_RET(lysp_stmt_container(ctx, child, &inout_p->node, &inout_p->child));
1743 break;
1744 case LY_STMT_LEAF:
1745 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &inout_p->node, &inout_p->child));
1746 break;
1747 case LY_STMT_LEAF_LIST:
1748 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &inout_p->node, &inout_p->child));
1749 break;
1750 case LY_STMT_LIST:
1751 LY_CHECK_RET(lysp_stmt_list(ctx, child, &inout_p->node, &inout_p->child));
1752 break;
1753 case LY_STMT_USES:
1754 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &inout_p->node, &inout_p->child));
1755 break;
1756 case LY_STMT_TYPEDEF:
1757 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &inout_p->node, &inout_p->typedefs));
1758 break;
1759 case LY_STMT_MUST:
1760 PARSER_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(stmt->kw));
1761 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &inout_p->musts));
1762 break;
1763 case LY_STMT_GROUPING:
1764 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &inout_p->node, &inout_p->groupings));
1765 break;
1766 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001767 LY_CHECK_RET(lysp_stmt_ext(ctx, child, stmt->kw, 0, &inout_p->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001768 break;
1769 default:
1770 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), ly_stmt2str(stmt->kw));
1771 return LY_EVALID;
1772 }
1773 }
1774
1775 if (!inout_p->child) {
1776 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(stmt->kw));
1777 return LY_EVALID;
1778 }
1779
1780 return LY_SUCCESS;
1781}
1782
1783/**
1784 * @brief Parse the action statement.
1785 *
1786 * @param[in] ctx parser context.
1787 * @param[in] stmt Source statement data from the parsed extension instance.
1788 * @param[in] parent Parent node to connect to (not into).
1789 * @param[in,out] actions Actions to add to.
1790 *
1791 * @return LY_ERR values.
1792 */
1793static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001794lysp_stmt_action(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02001795 struct lysp_node_action **actions)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001796{
1797 struct lysp_node_action *act;
1798
1799 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1800
1801 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
1802
1803 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &act->name));
1804 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
1805 act->parent = parent;
1806
1807 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1808 switch (child->kw) {
1809 case LY_STMT_DESCRIPTION:
1810 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->dsc, Y_STR_ARG, &act->exts));
1811 break;
1812 case LY_STMT_IF_FEATURE:
1813 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &act->iffeatures, Y_STR_ARG, &act->exts));
1814 break;
1815 case LY_STMT_REFERENCE:
1816 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &act->ref, Y_STR_ARG, &act->exts));
1817 break;
1818 case LY_STMT_STATUS:
1819 LY_CHECK_RET(lysp_stmt_status(ctx, child, &act->flags, &act->exts));
1820 break;
1821
1822 case LY_STMT_INPUT:
1823 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->input));
1824 break;
1825 case LY_STMT_OUTPUT:
1826 LY_CHECK_RET(lysp_stmt_inout(ctx, child, &act->node, &act->output));
1827 break;
1828
1829 case LY_STMT_TYPEDEF:
1830 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &act->node, &act->typedefs));
1831 break;
1832 case LY_STMT_GROUPING:
1833 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &act->node, &act->groupings));
1834 break;
1835 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001836 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 +01001837 break;
1838 default:
1839 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), parent ? "action" : "rpc");
1840 return LY_EVALID;
1841 }
1842 }
1843
1844 /* always initialize inout, they are technically present (needed for later deviations/refines) */
1845 if (!act->input.nodetype) {
1846 act->input.nodetype = LYS_INPUT;
1847 act->input.parent = &act->node;
1848 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
1849 }
1850 if (!act->output.nodetype) {
1851 act->output.nodetype = LYS_OUTPUT;
1852 act->output.parent = &act->node;
1853 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
1854 }
1855
1856 return LY_SUCCESS;
1857}
1858
1859/**
1860 * @brief Parse the notification statement.
1861 *
1862 * @param[in] ctx parser context.
1863 * @param[in] stmt Source statement data from the parsed extension instance.
1864 * @param[in] parent Parent node to connect to (not into).
1865 * @param[in,out] notifs Notifications to add to.
1866 *
1867 * @return LY_ERR values.
1868 */
1869static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001870lysp_stmt_notif(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02001871 struct lysp_node_notif **notifs)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001872{
1873 struct lysp_node_notif *notif;
1874
1875 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1876
1877 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
1878
1879 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &notif->name));
1880 notif->nodetype = LYS_NOTIF;
1881 notif->parent = parent;
1882
1883 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1884 switch (child->kw) {
1885 case LY_STMT_DESCRIPTION:
1886 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
1887 break;
1888 case LY_STMT_IF_FEATURE:
1889 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &notif->iffeatures, Y_STR_ARG, &notif->exts));
1890 break;
1891 case LY_STMT_REFERENCE:
1892 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &notif->ref, Y_STR_ARG, &notif->exts));
1893 break;
1894 case LY_STMT_STATUS:
1895 LY_CHECK_RET(lysp_stmt_status(ctx, child, &notif->flags, &notif->exts));
1896 break;
1897
1898 case LY_STMT_ANYDATA:
1899 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
1900 /* fall through */
1901 case LY_STMT_ANYXML:
1902 LY_CHECK_RET(lysp_stmt_any(ctx, child, &notif->node, &notif->child));
1903 break;
1904 case LY_STMT_CHOICE:
1905 LY_CHECK_RET(lysp_stmt_case(ctx, child, &notif->node, &notif->child));
1906 break;
1907 case LY_STMT_CONTAINER:
1908 LY_CHECK_RET(lysp_stmt_container(ctx, child, &notif->node, &notif->child));
1909 break;
1910 case LY_STMT_LEAF:
1911 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &notif->node, &notif->child));
1912 break;
1913 case LY_STMT_LEAF_LIST:
1914 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &notif->node, &notif->child));
1915 break;
1916 case LY_STMT_LIST:
1917 LY_CHECK_RET(lysp_stmt_list(ctx, child, &notif->node, &notif->child));
1918 break;
1919 case LY_STMT_USES:
1920 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &notif->node, &notif->child));
1921 break;
1922
1923 case LY_STMT_MUST:
1924 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
1925 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &notif->musts));
1926 break;
1927 case LY_STMT_TYPEDEF:
1928 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &notif->node, &notif->typedefs));
1929 break;
1930 case LY_STMT_GROUPING:
1931 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &notif->node, &notif->groupings));
1932 break;
1933 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001934 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_NOTIFICATION, 0, &notif->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001935 break;
1936 default:
1937 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "notification");
1938 return LY_EVALID;
1939 }
1940 }
1941
1942 return LY_SUCCESS;
1943}
1944
1945/**
1946 * @brief Parse the grouping statement.
1947 *
1948 * @param[in] ctx parser context.
1949 * @param[in] stmt Source statement data from the parsed extension instance.
1950 * @param[in] parent Parent node to connect to (not into).
1951 * @param[in,out] groupings Groupings to add to.
1952 *
1953 * @return LY_ERR values.
1954 */
1955static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001956lysp_stmt_grouping(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02001957 struct lysp_node_grp **groupings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01001958{
1959 struct lysp_node_grp *grp;
1960
1961 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
1962
1963 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
1964
1965 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &grp->name));
1966 grp->nodetype = LYS_GROUPING;
1967 grp->parent = parent;
1968
1969 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
1970 switch (child->kw) {
1971 case LY_STMT_DESCRIPTION:
1972 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
1973 break;
1974 case LY_STMT_REFERENCE:
1975 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &grp->ref, Y_STR_ARG, &grp->exts));
1976 break;
1977 case LY_STMT_STATUS:
1978 LY_CHECK_RET(lysp_stmt_status(ctx, child, &grp->flags, &grp->exts));
1979 break;
1980
1981 case LY_STMT_ANYDATA:
1982 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
1983 /* fall through */
1984 case LY_STMT_ANYXML:
1985 LY_CHECK_RET(lysp_stmt_any(ctx, child, &grp->node, &grp->child));
1986 break;
1987 case LY_STMT_CHOICE:
1988 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &grp->node, &grp->child));
1989 break;
1990 case LY_STMT_CONTAINER:
1991 LY_CHECK_RET(lysp_stmt_container(ctx, child, &grp->node, &grp->child));
1992 break;
1993 case LY_STMT_LEAF:
1994 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &grp->node, &grp->child));
1995 break;
1996 case LY_STMT_LEAF_LIST:
1997 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &grp->node, &grp->child));
1998 break;
1999 case LY_STMT_LIST:
2000 LY_CHECK_RET(lysp_stmt_list(ctx, child, &grp->node, &grp->child));
2001 break;
2002 case LY_STMT_USES:
2003 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &grp->node, &grp->child));
2004 break;
2005
2006 case LY_STMT_TYPEDEF:
2007 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &grp->node, &grp->typedefs));
2008 break;
2009 case LY_STMT_ACTION:
2010 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
2011 LY_CHECK_RET(lysp_stmt_action(ctx, child, &grp->node, &grp->actions));
2012 break;
2013 case LY_STMT_GROUPING:
2014 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &grp->node, &grp->groupings));
2015 break;
2016 case LY_STMT_NOTIFICATION:
2017 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
2018 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &grp->node, &grp->notifs));
2019 break;
2020 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002021 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_GROUPING, 0, &grp->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002022 break;
2023 default:
2024 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "grouping");
2025 return LY_EVALID;
2026 }
2027 }
2028
2029 return LY_SUCCESS;
2030}
2031
2032/**
2033 * @brief Parse the augment statement.
2034 *
2035 * @param[in] ctx parser context.
2036 * @param[in] stmt Source statement data from the parsed extension instance.
2037 * @param[in] parent Parent node to connect to (not into).
2038 * @param[in,out] augments Augments to add to.
2039 *
2040 * @return LY_ERR values.
2041 */
2042static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002043lysp_stmt_augment(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002044 struct lysp_node_augment **augments)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002045{
2046 struct lysp_node_augment *aug;
2047
2048 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
2049
2050 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
2051
2052 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &aug->nodeid));
2053 aug->nodetype = LYS_AUGMENT;
2054 aug->parent = parent;
2055
2056 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2057 switch (child->kw) {
2058 case LY_STMT_DESCRIPTION:
2059 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
2060 break;
2061 case LY_STMT_IF_FEATURE:
2062 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &aug->iffeatures, Y_STR_ARG, &aug->exts));
2063 break;
2064 case LY_STMT_REFERENCE:
2065 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &aug->ref, Y_STR_ARG, &aug->exts));
2066 break;
2067 case LY_STMT_STATUS:
2068 LY_CHECK_RET(lysp_stmt_status(ctx, child, &aug->flags, &aug->exts));
2069 break;
2070 case LY_STMT_WHEN:
2071 LY_CHECK_RET(lysp_stmt_when(ctx, child, &aug->when));
2072 break;
2073
2074 case LY_STMT_ANYDATA:
2075 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
2076 /* fall through */
2077 case LY_STMT_ANYXML:
2078 LY_CHECK_RET(lysp_stmt_any(ctx, child, &aug->node, &aug->child));
2079 break;
2080 case LY_STMT_CASE:
2081 LY_CHECK_RET(lysp_stmt_case(ctx, child, &aug->node, &aug->child));
2082 break;
2083 case LY_STMT_CHOICE:
2084 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &aug->node, &aug->child));
2085 break;
2086 case LY_STMT_CONTAINER:
2087 LY_CHECK_RET(lysp_stmt_container(ctx, child, &aug->node, &aug->child));
2088 break;
2089 case LY_STMT_LEAF:
2090 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &aug->node, &aug->child));
2091 break;
2092 case LY_STMT_LEAF_LIST:
2093 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &aug->node, &aug->child));
2094 break;
2095 case LY_STMT_LIST:
2096 LY_CHECK_RET(lysp_stmt_list(ctx, child, &aug->node, &aug->child));
2097 break;
2098 case LY_STMT_USES:
2099 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &aug->node, &aug->child));
2100 break;
2101
2102 case LY_STMT_ACTION:
2103 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
2104 LY_CHECK_RET(lysp_stmt_action(ctx, child, &aug->node, &aug->actions));
2105 break;
2106 case LY_STMT_NOTIFICATION:
2107 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
2108 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &aug->node, &aug->notifs));
2109 break;
2110 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002111 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_AUGMENT, 0, &aug->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002112 break;
2113 default:
2114 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "augment");
2115 return LY_EVALID;
2116 }
2117 }
2118
2119 return LY_SUCCESS;
2120}
2121
2122/**
2123 * @brief Parse the uses statement.
2124 *
2125 * @param[in] ctx parser context.
2126 * @param[in] stmt Source statement data from the parsed extension instance.
2127 * @param[in] parent Parent node to connect to (not into).
2128 * @param[in,out] siblings Siblings to add to.
2129 *
2130 * @return LY_ERR values.
2131 */
2132static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002133lysp_stmt_uses(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002134 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002135{
2136 struct lysp_node_uses *uses;
2137
2138 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
2139
2140 /* create uses structure */
2141 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
2142
2143 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &uses->name));
2144 uses->nodetype = LYS_USES;
2145 uses->parent = parent;
2146
2147 /* parse substatements */
2148 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2149 switch (child->kw) {
2150 case LY_STMT_DESCRIPTION:
2151 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
2152 break;
2153 case LY_STMT_IF_FEATURE:
2154 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &uses->iffeatures, Y_STR_ARG, &uses->exts));
2155 break;
2156 case LY_STMT_REFERENCE:
2157 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &uses->ref, Y_STR_ARG, &uses->exts));
2158 break;
2159 case LY_STMT_STATUS:
2160 LY_CHECK_RET(lysp_stmt_status(ctx, child, &uses->flags, &uses->exts));
2161 break;
2162 case LY_STMT_WHEN:
2163 LY_CHECK_RET(lysp_stmt_when(ctx, child, &uses->when));
2164 break;
2165
2166 case LY_STMT_REFINE:
2167 LY_CHECK_RET(lysp_stmt_refine(ctx, child, &uses->refines));
2168 break;
2169 case LY_STMT_AUGMENT:
2170 LY_CHECK_RET(lysp_stmt_augment(ctx, child, &uses->node, &uses->augments));
2171 break;
2172 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002173 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_USES, 0, &uses->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002174 break;
2175 default:
2176 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "uses");
2177 return LY_EVALID;
2178 }
2179 }
2180
2181 return LY_SUCCESS;
2182}
2183
2184/**
2185 * @brief Parse the case statement.
2186 *
2187 * @param[in] ctx parser context.
2188 * @param[in] stmt Source statement data from the parsed extension instance.
2189 * @param[in] parent Parent node to connect to (not into).
2190 * @param[in,out] siblings Siblings to add to.
2191 *
2192 * @return LY_ERR values.
2193 */
2194static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002195lysp_stmt_case(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002196 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002197{
2198 struct lysp_node_case *cas;
2199
2200 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2201
2202 /* create new case structure */
2203 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
2204
2205 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cas->name));
2206 cas->nodetype = LYS_CASE;
2207 cas->parent = parent;
2208
2209 /* parse substatements */
2210 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2211 switch (child->kw) {
2212 case LY_STMT_DESCRIPTION:
2213 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
2214 break;
2215 case LY_STMT_IF_FEATURE:
2216 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cas->iffeatures, Y_STR_ARG, &cas->exts));
2217 break;
2218 case LY_STMT_REFERENCE:
2219 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cas->ref, Y_STR_ARG, &cas->exts));
2220 break;
2221 case LY_STMT_STATUS:
2222 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cas->flags, &cas->exts));
2223 break;
2224 case LY_STMT_WHEN:
2225 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cas->when));
2226 break;
2227
2228 case LY_STMT_ANYDATA:
2229 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
2230 /* fall through */
2231 case LY_STMT_ANYXML:
2232 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cas->node, &cas->child));
2233 break;
2234 case LY_STMT_CHOICE:
2235 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cas->node, &cas->child));
2236 break;
2237 case LY_STMT_CONTAINER:
2238 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cas->node, &cas->child));
2239 break;
2240 case LY_STMT_LEAF:
2241 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cas->node, &cas->child));
2242 break;
2243 case LY_STMT_LEAF_LIST:
2244 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cas->node, &cas->child));
2245 break;
2246 case LY_STMT_LIST:
2247 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cas->node, &cas->child));
2248 break;
2249 case LY_STMT_USES:
2250 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cas->node, &cas->child));
2251 break;
2252 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002253 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CASE, 0, &cas->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002254 break;
2255 default:
2256 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "case");
2257 return LY_EVALID;
2258 }
2259 }
2260 return LY_SUCCESS;
2261}
2262
2263/**
2264 * @brief Parse the choice statement.
2265 *
2266 * @param[in] ctx parser context.
2267 * @param[in] stmt Source statement data from the parsed extension instance.
2268 * @param[in] parent Parent node to connect to (not into).
2269 * @param[in,out] siblings Siblings to add to.
2270 *
2271 * @return LY_ERR values.
2272 */
2273static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002274lysp_stmt_choice(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002275 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002276{
2277 struct lysp_node_choice *choice;
2278
2279 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2280
2281 /* create new choice structure */
2282 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
2283
2284 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &choice->name));
2285 choice->nodetype = LYS_CHOICE;
2286 choice->parent = parent;
2287
2288 /* parse substatements */
2289 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2290 switch (child->kw) {
2291 case LY_STMT_CONFIG:
2292 LY_CHECK_RET(lysp_stmt_config(ctx, child, &choice->flags, &choice->exts));
2293 break;
2294 case LY_STMT_DESCRIPTION:
2295 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
2296 break;
2297 case LY_STMT_IF_FEATURE:
2298 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &choice->iffeatures, Y_STR_ARG, &choice->exts));
2299 break;
2300 case LY_STMT_MANDATORY:
2301 LY_CHECK_RET(lysp_stmt_mandatory(ctx, child, &choice->flags, &choice->exts));
2302 break;
2303 case LY_STMT_REFERENCE:
2304 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->ref, Y_STR_ARG, &choice->exts));
2305 break;
2306 case LY_STMT_STATUS:
2307 LY_CHECK_RET(lysp_stmt_status(ctx, child, &choice->flags, &choice->exts));
2308 break;
2309 case LY_STMT_WHEN:
2310 LY_CHECK_RET(lysp_stmt_when(ctx, child, &choice->when));
2311 break;
2312 case LY_STMT_DEFAULT:
2313 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 +01002314 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002315 break;
2316 case LY_STMT_ANYDATA:
2317 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
2318 /* fall through */
2319 case LY_STMT_ANYXML:
2320 LY_CHECK_RET(lysp_stmt_any(ctx, child, &choice->node, &choice->child));
2321 break;
2322 case LY_STMT_CASE:
2323 LY_CHECK_RET(lysp_stmt_case(ctx, child, &choice->node, &choice->child));
2324 break;
2325 case LY_STMT_CHOICE:
2326 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
2327 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &choice->node, &choice->child));
2328 break;
2329 case LY_STMT_CONTAINER:
2330 LY_CHECK_RET(lysp_stmt_container(ctx, child, &choice->node, &choice->child));
2331 break;
2332 case LY_STMT_LEAF:
2333 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &choice->node, &choice->child));
2334 break;
2335 case LY_STMT_LEAF_LIST:
2336 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &choice->node, &choice->child));
2337 break;
2338 case LY_STMT_LIST:
2339 LY_CHECK_RET(lysp_stmt_list(ctx, child, &choice->node, &choice->child));
2340 break;
2341 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002342 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CHOICE, 0, &choice->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002343 break;
2344 default:
2345 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "choice");
2346 return LY_EVALID;
2347 }
2348 }
2349 return LY_SUCCESS;
2350}
2351
2352/**
2353 * @brief Parse the container statement.
2354 *
2355 * @param[in] ctx parser context.
2356 * @param[in] stmt Source statement data from the parsed extension instance.
2357 * @param[in] parent Parent node to connect to (not into).
2358 * @param[in,out] siblings Siblings to add to.
2359 *
2360 * @return LY_ERR values.
2361 */
2362static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002363lysp_stmt_container(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002364 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002365{
2366 struct lysp_node_container *cont;
2367
2368 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2369
2370 /* create new container structure */
2371 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
2372
2373 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &cont->name));
2374 cont->nodetype = LYS_CONTAINER;
2375 cont->parent = parent;
2376
2377 /* parse substatements */
2378 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2379 switch (child->kw) {
2380 case LY_STMT_CONFIG:
2381 LY_CHECK_RET(lysp_stmt_config(ctx, child, &cont->flags, &cont->exts));
2382 break;
2383 case LY_STMT_DESCRIPTION:
2384 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
2385 break;
2386 case LY_STMT_IF_FEATURE:
2387 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &cont->iffeatures, Y_STR_ARG, &cont->exts));
2388 break;
2389 case LY_STMT_REFERENCE:
2390 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->ref, Y_STR_ARG, &cont->exts));
2391 break;
2392 case LY_STMT_STATUS:
2393 LY_CHECK_RET(lysp_stmt_status(ctx, child, &cont->flags, &cont->exts));
2394 break;
2395 case LY_STMT_WHEN:
2396 LY_CHECK_RET(lysp_stmt_when(ctx, child, &cont->when));
2397 break;
2398 case LY_STMT_PRESENCE:
2399 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &cont->presence, Y_STR_ARG, &cont->exts));
2400 break;
2401 case LY_STMT_ANYDATA:
2402 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
2403 /* fall through */
2404 case LY_STMT_ANYXML:
2405 LY_CHECK_RET(lysp_stmt_any(ctx, child, &cont->node, &cont->child));
2406 break;
2407 case LY_STMT_CHOICE:
2408 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &cont->node, &cont->child));
2409 break;
2410 case LY_STMT_CONTAINER:
2411 LY_CHECK_RET(lysp_stmt_container(ctx, child, &cont->node, &cont->child));
2412 break;
2413 case LY_STMT_LEAF:
2414 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &cont->node, &cont->child));
2415 break;
2416 case LY_STMT_LEAF_LIST:
2417 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &cont->node, &cont->child));
2418 break;
2419 case LY_STMT_LIST:
2420 LY_CHECK_RET(lysp_stmt_list(ctx, child, &cont->node, &cont->child));
2421 break;
2422 case LY_STMT_USES:
2423 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &cont->node, &cont->child));
2424 break;
2425
2426 case LY_STMT_TYPEDEF:
2427 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &cont->node, &cont->typedefs));
2428 break;
2429 case LY_STMT_MUST:
2430 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &cont->musts));
2431 break;
2432 case LY_STMT_ACTION:
2433 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
2434 LY_CHECK_RET(lysp_stmt_action(ctx, child, &cont->node, &cont->actions));
2435 break;
2436 case LY_STMT_GROUPING:
2437 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &cont->node, &cont->groupings));
2438 break;
2439 case LY_STMT_NOTIFICATION:
2440 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
2441 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &cont->node, &cont->notifs));
2442 break;
2443 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002444 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_CONTAINER, 0, &cont->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002445 break;
2446 default:
2447 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "container");
2448 return LY_EVALID;
2449 }
2450 }
2451
2452 return LY_SUCCESS;
2453}
2454
2455/**
2456 * @brief Parse the list statement.
2457 *
2458 * @param[in] ctx parser context.
2459 * @param[in] stmt Source statement data from the parsed extension instance.
2460 * @param[in] parent Parent node to connect to (not into).
2461 * @param[in,out] siblings Siblings to add to.
2462 *
2463 * @return LY_ERR values.
2464 */
2465static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002466lysp_stmt_list(struct lysp_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_node *parent,
Michal Vasko59892dd2022-05-13 11:02:30 +02002467 struct lysp_node **siblings)
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002468{
2469 struct lysp_node_list *list;
2470
2471 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_IDENTIF_ARG, stmt->arg));
2472
2473 /* create new list structure */
2474 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
2475
2476 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &list->name));
2477 list->nodetype = LYS_LIST;
2478 list->parent = parent;
2479
2480 /* parse substatements */
2481 for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
2482 switch (child->kw) {
2483 case LY_STMT_CONFIG:
2484 LY_CHECK_RET(lysp_stmt_config(ctx, child, &list->flags, &list->exts));
2485 break;
2486 case LY_STMT_DESCRIPTION:
2487 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->dsc, Y_STR_ARG, &list->exts));
2488 break;
2489 case LY_STMT_IF_FEATURE:
2490 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->iffeatures, Y_STR_ARG, &list->exts));
2491 break;
2492 case LY_STMT_REFERENCE:
2493 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->ref, Y_STR_ARG, &list->exts));
2494 break;
2495 case LY_STMT_STATUS:
2496 LY_CHECK_RET(lysp_stmt_status(ctx, child, &list->flags, &list->exts));
2497 break;
2498 case LY_STMT_WHEN:
2499 LY_CHECK_RET(lysp_stmt_when(ctx, child, &list->when));
2500 break;
2501 case LY_STMT_KEY:
2502 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &list->key, Y_STR_ARG, &list->exts));
2503 break;
2504 case LY_STMT_MAX_ELEMENTS:
2505 LY_CHECK_RET(lysp_stmt_maxelements(ctx, child, &list->max, &list->flags, &list->exts));
2506 break;
2507 case LY_STMT_MIN_ELEMENTS:
2508 LY_CHECK_RET(lysp_stmt_minelements(ctx, child, &list->min, &list->flags, &list->exts));
2509 break;
2510 case LY_STMT_ORDERED_BY:
2511 LY_CHECK_RET(lysp_stmt_orderedby(ctx, child, &list->flags, &list->exts));
2512 break;
2513 case LY_STMT_UNIQUE:
2514 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, &list->uniques, Y_STR_ARG, &list->exts));
2515 break;
2516
2517 case LY_STMT_ANYDATA:
2518 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
2519 /* fall through */
2520 case LY_STMT_ANYXML:
2521 LY_CHECK_RET(lysp_stmt_any(ctx, child, &list->node, &list->child));
2522 break;
2523 case LY_STMT_CHOICE:
2524 LY_CHECK_RET(lysp_stmt_choice(ctx, child, &list->node, &list->child));
2525 break;
2526 case LY_STMT_CONTAINER:
2527 LY_CHECK_RET(lysp_stmt_container(ctx, child, &list->node, &list->child));
2528 break;
2529 case LY_STMT_LEAF:
2530 LY_CHECK_RET(lysp_stmt_leaf(ctx, child, &list->node, &list->child));
2531 break;
2532 case LY_STMT_LEAF_LIST:
2533 LY_CHECK_RET(lysp_stmt_leaflist(ctx, child, &list->node, &list->child));
2534 break;
2535 case LY_STMT_LIST:
2536 LY_CHECK_RET(lysp_stmt_list(ctx, child, &list->node, &list->child));
2537 break;
2538 case LY_STMT_USES:
2539 LY_CHECK_RET(lysp_stmt_uses(ctx, child, &list->node, &list->child));
2540 break;
2541
2542 case LY_STMT_TYPEDEF:
2543 LY_CHECK_RET(lysp_stmt_typedef(ctx, child, &list->node, &list->typedefs));
2544 break;
2545 case LY_STMT_MUST:
2546 LY_CHECK_RET(lysp_stmt_restrs(ctx, child, &list->musts));
2547 break;
2548 case LY_STMT_ACTION:
2549 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
2550 LY_CHECK_RET(lysp_stmt_action(ctx, child, &list->node, &list->actions));
2551 break;
2552 case LY_STMT_GROUPING:
2553 LY_CHECK_RET(lysp_stmt_grouping(ctx, child, &list->node, &list->groupings));
2554 break;
2555 case LY_STMT_NOTIFICATION:
2556 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
2557 LY_CHECK_RET(lysp_stmt_notif(ctx, child, &list->node, &list->notifs));
2558 break;
2559 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002560 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LY_STMT_LIST, 0, &list->exts));
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002561 break;
2562 default:
2563 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(child->kw), "list");
2564 return LY_EVALID;
2565 }
2566 }
2567
2568 return LY_SUCCESS;
2569}
2570
Radek Krejci335332a2019-09-05 13:03:35 +02002571LY_ERR
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002572lysp_stmt_parse(struct lysc_ctx *ctx, const struct lysp_stmt *stmt, void **result, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +02002573{
Radek Krejciad5963b2019-09-06 16:03:05 +02002574 LY_ERR ret = LY_SUCCESS;
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002575 uint16_t flags;
Michal Vaskod0625d72022-10-06 15:02:50 +02002576 struct lysp_ctx pctx = {0};
Michal Vasko8a67eff2021-12-07 14:04:47 +01002577 struct ly_set pmods = {0};
2578 void *objs;
Radek Krejci335332a2019-09-05 13:03:35 +02002579
Michal Vasko8a67eff2021-12-07 14:04:47 +01002580 /* local context */
Michal Vaskob36053d2020-03-26 15:49:30 +01002581 pctx.format = LYS_IN_YANG;
Michal Vasko8a67eff2021-12-07 14:04:47 +01002582 pctx.parsed_mods = &pmods;
2583 objs = &ctx->pmod;
2584 pmods.objs = objs;
2585 pmods.count = 1;
Radek Krejci2efc45b2020-12-22 16:25:44 +01002586
Radek Krejciddace2c2021-01-08 11:30:56 +01002587 LOG_LOCSET(NULL, NULL, ctx->path, NULL);
Radek Krejci335332a2019-09-05 13:03:35 +02002588
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002589 switch (stmt->kw) {
2590 case LY_STMT_ACTION:
2591 case LY_STMT_RPC:
2592 ret = lysp_stmt_action(&pctx, stmt, NULL, (struct lysp_node_action **)result);
2593 break;
2594 case LY_STMT_ANYDATA:
2595 case LY_STMT_ANYXML:
2596 ret = lysp_stmt_any(&pctx, stmt, NULL, (struct lysp_node **)result);
2597 break;
2598 case LY_STMT_AUGMENT:
2599 ret = lysp_stmt_augment(&pctx, stmt, NULL, (struct lysp_node_augment **)result);
2600 break;
2601 case LY_STMT_BASE:
2602 ret = lysp_stmt_text_fields(&pctx, stmt, (const char ***)result, Y_PREF_IDENTIF_ARG, exts);
2603 break;
2604 case LY_STMT_BIT:
2605 case LY_STMT_ENUM:
2606 ret = lysp_stmt_type_enum(&pctx, stmt, (struct lysp_type_enum **)result);
2607 break;
2608 case LY_STMT_CASE:
2609 ret = lysp_stmt_case(&pctx, stmt, NULL, (struct lysp_node **)result);
2610 break;
2611 case LY_STMT_CHOICE:
2612 ret = lysp_stmt_choice(&pctx, stmt, NULL, (struct lysp_node **)result);
2613 break;
2614 case LY_STMT_CONFIG:
Michal Vasko39ed7a22022-02-21 08:34:18 +01002615 assert(*result);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002616 ret = lysp_stmt_config(&pctx, stmt, *(uint16_t **)result, exts);
2617 break;
2618 case LY_STMT_CONTACT:
2619 case LY_STMT_DESCRIPTION:
2620 case LY_STMT_ERROR_APP_TAG:
2621 case LY_STMT_ERROR_MESSAGE:
2622 case LY_STMT_KEY:
2623 case LY_STMT_NAMESPACE:
2624 case LY_STMT_ORGANIZATION:
2625 case LY_STMT_PRESENCE:
2626 case LY_STMT_REFERENCE:
2627 case LY_STMT_UNITS:
2628 ret = lysp_stmt_text_field(&pctx, stmt, 0, (const char **)result, Y_STR_ARG, exts);
2629 break;
2630 case LY_STMT_CONTAINER:
2631 ret = lysp_stmt_container(&pctx, stmt, NULL, (struct lysp_node **)result);
2632 break;
2633 case LY_STMT_DEFAULT:
2634 case LY_STMT_IF_FEATURE:
2635 case LY_STMT_UNIQUE:
2636 ret = lysp_stmt_qnames(&pctx, stmt, (struct lysp_qname **)result, Y_STR_ARG, exts);
2637 break;
2638 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002639 ret = lysp_stmt_ext(&pctx, stmt, LY_STMT_EXTENSION_INSTANCE, 0, exts);
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002640 break;
2641 case LY_STMT_FRACTION_DIGITS:
2642 ret = lysp_stmt_type_fracdigits(&pctx, stmt, *(uint8_t **)result, exts);
2643 break;
2644 case LY_STMT_GROUPING:
2645 ret = lysp_stmt_grouping(&pctx, stmt, NULL, (struct lysp_node_grp **)result);
2646 break;
2647 case LY_STMT_INPUT:
2648 case LY_STMT_OUTPUT: {
2649 struct lysp_node_action_inout *inout;
2650
2651 *result = inout = calloc(1, sizeof *inout);
2652 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
2653 ret = lysp_stmt_inout(&pctx, stmt, NULL, inout);
2654 break;
2655 }
2656 case LY_STMT_LEAF:
2657 ret = lysp_stmt_leaf(&pctx, stmt, NULL, (struct lysp_node **)result);
2658 break;
2659 case LY_STMT_LEAF_LIST:
2660 ret = lysp_stmt_leaflist(&pctx, stmt, NULL, (struct lysp_node **)result);
2661 break;
2662 case LY_STMT_LENGTH:
2663 case LY_STMT_MUST:
2664 case LY_STMT_RANGE:
2665 ret = lysp_stmt_restrs(&pctx, stmt, (struct lysp_restr **)result);
2666 break;
2667 case LY_STMT_LIST:
2668 ret = lysp_stmt_list(&pctx, stmt, NULL, (struct lysp_node **)result);
2669 break;
2670 case LY_STMT_MANDATORY:
2671 ret = lysp_stmt_mandatory(&pctx, stmt, *(uint16_t **)result, exts);
2672 break;
2673 case LY_STMT_MAX_ELEMENTS:
2674 flags = 0;
2675 ret = lysp_stmt_maxelements(&pctx, stmt, *(uint32_t **)result, &flags, exts);
2676 break;
2677 case LY_STMT_MIN_ELEMENTS:
2678 flags = 0;
2679 ret = lysp_stmt_minelements(&pctx, stmt, *(uint32_t **)result, &flags, exts);
2680 break;
2681 case LY_STMT_MODIFIER:
2682 ret = lysp_stmt_type_pattern_modifier(&pctx, stmt, (const char **)result, exts);
2683 break;
2684 case LY_STMT_NOTIFICATION:
2685 ret = lysp_stmt_notif(&pctx, stmt, NULL, (struct lysp_node_notif **)result);
2686 break;
2687 case LY_STMT_ORDERED_BY:
2688 ret = lysp_stmt_orderedby(&pctx, stmt, *(uint16_t **)result, exts);
2689 break;
2690 case LY_STMT_PATH: {
2691 const char *str_path = NULL;
2692
2693 LY_CHECK_RET(lysp_stmt_text_field(&pctx, stmt, 0, &str_path, Y_STR_ARG, exts));
Michal Vaskoed725d72021-06-23 12:03:45 +02002694 ret = ly_path_parse(ctx->ctx, NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002695 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, (struct lyxp_expr **)result);
2696 lydict_remove(ctx->ctx, str_path);
2697 break;
2698 }
2699 case LY_STMT_PATTERN:
2700 ret = lysp_stmt_type_pattern(&pctx, stmt, (struct lysp_restr **)result);
2701 break;
2702 case LY_STMT_POSITION:
2703 case LY_STMT_VALUE:
2704 flags = 0;
2705 ret = lysp_stmt_type_enum_value_pos(&pctx, stmt, *(int64_t **)result, &flags, exts);
2706 break;
2707 case LY_STMT_PREFIX:
2708 ret = lysp_stmt_text_field(&pctx, stmt, 0, (const char **)result, Y_IDENTIF_ARG, exts);
2709 break;
2710 case LY_STMT_REFINE:
2711 ret = lysp_stmt_refine(&pctx, stmt, (struct lysp_refine **)result);
2712 break;
2713 case LY_STMT_REQUIRE_INSTANCE:
2714 flags = 0;
2715 ret = lysp_stmt_type_reqinstance(&pctx, stmt, *(uint8_t **)result, &flags, exts);
2716 break;
Michal Vasko69730152020-10-09 16:30:07 +02002717 case LY_STMT_STATUS:
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002718 ret = lysp_stmt_status(&pctx, stmt, *(uint16_t **)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +02002719 break;
Radek Krejci335332a2019-09-05 13:03:35 +02002720 case LY_STMT_TYPE: {
2721 struct lysp_type *type;
Radek Krejci335332a2019-09-05 13:03:35 +02002722
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002723 *result = type = calloc(1, sizeof *type);
2724 LY_CHECK_ERR_RET(!type, LOGMEM(ctx->ctx), LY_EMEM);
2725 ret = lysp_stmt_type(&pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +02002726 break;
Radek Krejci0f969882020-08-21 16:56:47 +02002727 }
Radek Krejci76c8c4e2021-02-17 10:16:48 +01002728 case LY_STMT_TYPEDEF:
2729 ret = lysp_stmt_typedef(&pctx, stmt, NULL, (struct lysp_tpdf **)result);
2730 break;
2731 case LY_STMT_USES:
2732 ret = lysp_stmt_uses(&pctx, stmt, NULL, (struct lysp_node **)result);
2733 break;
2734 case LY_STMT_WHEN:
2735 ret = lysp_stmt_when(&pctx, stmt, (struct lysp_when **)result);
2736 break;
Radek Krejci335332a2019-09-05 13:03:35 +02002737 default:
2738 LOGINT(ctx->ctx);
2739 return LY_EINT;
2740 }
2741
Radek Krejciddace2c2021-01-08 11:30:56 +01002742 LOG_LOCBACK(0, 0, 1, 0);
Radek Krejciad5963b2019-09-06 16:03:05 +02002743 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +02002744}
Michal Vasko59892dd2022-05-13 11:02:30 +02002745
2746void
2747lys_parser_fill_filepath(struct ly_ctx *ctx, struct ly_in *in, const char **filepath)
2748{
2749 char path[PATH_MAX];
2750
2751#ifndef __APPLE__
2752 char proc_path[32];
2753 int len;
2754#endif
2755
2756 LY_CHECK_ARG_RET(NULL, ctx, in, filepath, );
2757 if (*filepath) {
2758 /* filepath already set */
2759 return;
2760 }
2761
2762 switch (in->type) {
2763 case LY_IN_FILEPATH:
2764 if (realpath(in->method.fpath.filepath, path) != NULL) {
2765 lydict_insert(ctx, path, 0, filepath);
2766 } else {
2767 lydict_insert(ctx, in->method.fpath.filepath, 0, filepath);
2768 }
2769
2770 break;
2771 case LY_IN_FD:
2772#ifdef __APPLE__
2773 if (fcntl(in->method.fd, F_GETPATH, path) != -1) {
2774 lydict_insert(ctx, path, 0, filepath);
2775 }
2776#elif defined _WIN32
2777 HANDLE h = _get_osfhandle(in->method.fd);
2778 FILE_NAME_INFO info;
2779 if (GetFileInformationByHandleEx(h, FileNameInfo, &info, sizeof info)) {
2780 char *buf = calloc(info.FileNameLength + 1 /* trailing NULL */, MB_CUR_MAX);
2781 len = wcstombs(buf, info.FileName, info.FileNameLength * MB_CUR_MAX);
2782 lydict_insert(ctx, buf, len, filepath);
2783 }
2784#else
2785 /* get URI if there is /proc */
2786 sprintf(proc_path, "/proc/self/fd/%d", in->method.fd);
2787 if ((len = readlink(proc_path, path, PATH_MAX - 1)) > 0) {
2788 lydict_insert(ctx, path, len, filepath);
2789 }
2790#endif
2791 break;
2792 case LY_IN_MEMORY:
2793 case LY_IN_FILE:
2794 /* nothing to do */
2795 break;
2796 default:
2797 LOGINT(ctx);
2798 break;
2799 }
2800}