blob: 566f39d71f1a2fd7030562be9ce9d83bccb2f1f0 [file] [log] [blame]
Radek Krejci335332a2019-09-05 13:03:35 +02001/**
2 * @file parser_stmt.c
3 * @author Radek Krejčí <rkrejci@cesnet.cz>
4 * @brief Parser of the extension substatements.
5 *
6 * Copyright (c) 2019 CESNET, z.s.p.o.
7 *
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
Radek Krejci335332a2019-09-05 13:03:35 +020015#include <assert.h>
16#include <ctype.h>
17#include <errno.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020018#include <stdint.h>
19#include <stdlib.h>
20#include <string.h>
Radek Krejci335332a2019-09-05 13:03:35 +020021
Radek Krejci535ea9f2020-05-29 16:01:05 +020022#include "common.h"
23#include "dict.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020024#include "in.h"
Radek Krejcid54412f2020-12-17 20:25:35 +010025#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010026#include "log.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020027#include "parser_schema.h"
Michal Vasko69730152020-10-09 16:30:07 +020028#include "path.h"
Michal Vasko1a7a7bd2020-10-16 14:39:15 +020029#include "schema_compile.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020030#include "tree.h"
Radek Krejci335332a2019-09-05 13:03:35 +020031#include "tree_schema.h"
32#include "tree_schema_internal.h"
33
34static LY_ERR
35lysp_stmt_validate_value(struct lys_parser_ctx *ctx, enum yang_arg val_type, const char *val)
36{
Radek Krejci857189e2020-09-01 13:26:36 +020037 uint8_t prefix = 0;
38 ly_bool first = 1;
Radek Krejci1deb5be2020-08-26 16:43:36 +020039 uint32_t c;
Radek Krejci335332a2019-09-05 13:03:35 +020040 size_t utf8_char_len;
41
42 while (*val) {
43 LY_CHECK_ERR_RET(ly_getutf8(&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +020044 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +020045
46 switch (val_type) {
47 case Y_IDENTIF_ARG:
48 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, NULL));
49 break;
50 case Y_PREF_IDENTIF_ARG:
51 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, first, &prefix));
52 break;
53 case Y_STR_ARG:
54 case Y_MAYBE_STR_ARG:
55 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
56 break;
57 }
58 first = 0;
59 }
60
61 return LY_SUCCESS;
62}
63
64/**
65 * @brief Parse extension instance.
66 *
67 * @param[in] ctx yang parser context for logging.
68 * @param[in,out] data Data to read from, always moved to currently handled character.
69 * @param[in] ext_name Extension instance substatement name (keyword).
70 * @param[in] ext_name_len Extension instance substatement name length.
71 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
72 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
73 * @param[in,out] exts Extension instances to add to.
74 *
75 * @return LY_ERR values.
76 */
77static LY_ERR
78lysp_stmt_ext(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, LYEXT_SUBSTMT insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +020079 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +020080{
81 struct lysp_ext_instance *e;
82
Michal Vaskob36053d2020-03-26 15:49:30 +010083 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +020084
85 /* store name and insubstmt info */
Radek Krejci011e4aa2020-09-04 15:22:31 +020086 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->stmt, 0, &e->name));
Radek Krejci335332a2019-09-05 13:03:35 +020087 e->insubstmt = insubstmt;
88 e->insubstmt_index = insubstmt_index;
89 /* TODO (duplicate) e->child = stmt->child; */
90
91 /* get optional argument */
92 if (stmt->arg) {
Radek Krejci011e4aa2020-09-04 15:22:31 +020093 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &e->argument));
Radek Krejci335332a2019-09-05 13:03:35 +020094 }
95
96 return LY_SUCCESS;
97}
98
99/**
100 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
101 * description, etc...
102 *
103 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200104 * @param[in] stmt Statement structure.
Radek Krejci335332a2019-09-05 13:03:35 +0200105 * @param[in] substmt Type of this substatement.
106 * @param[in] substmt_index Index of this substatement.
107 * @param[in,out] value Place to store the parsed value.
108 * @param[in] arg Type of the YANG keyword argument (of the value).
109 * @param[in,out] exts Extension instances to add to.
110 *
111 * @return LY_ERR values.
112 */
113static LY_ERR
114lysp_stmt_text_field(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Radek Krejci0f969882020-08-21 16:56:47 +0200115 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200116{
117 const struct lysp_stmt *child;
118
119 if (*value) {
120 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
121 return LY_EVALID;
122 }
123
124 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200125 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, value));
Radek Krejci335332a2019-09-05 13:03:35 +0200126
127 for (child = stmt->child; child; child = child->next) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200128 struct ly_in *in;
129 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100130 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200131 ly_in_free(in, 0);
Radek Krejci335332a2019-09-05 13:03:35 +0200132
133 switch (kw) {
134 case LY_STMT_EXTENSION_INSTANCE:
135 LY_CHECK_RET(lysp_stmt_ext(ctx, child, substmt, substmt_index, exts));
136 break;
137 default:
138 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
139 return LY_EVALID;
140 }
141 }
142 return LY_SUCCESS;
143}
144
145/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200146 * @brief Parse a qname that can have more instances such as if-feature.
147 *
148 * @param[in] ctx yang parser context for logging.
149 * @param[in,out] data Data to read from, always moved to currently handled character.
150 * @param[in] substmt Type of this substatement.
151 * @param[in,out] qnames Parsed qnames to add to.
152 * @param[in] arg Type of the expected argument.
153 * @param[in,out] exts Extension instances to add to.
154 *
155 * @return LY_ERR values.
156 */
157static LY_ERR
158lysp_stmt_qnames(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, LYEXT_SUBSTMT substmt,
159 struct lysp_qname **qnames, enum yang_arg arg, struct lysp_ext_instance **exts)
160{
161 struct lysp_qname *item;
162 const struct lysp_stmt *child;
163
164 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
165
166 /* allocate new pointer */
167 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
168 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200169 item->mod = ctx->parsed_mod;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200170
171 for (child = stmt->child; child; child = child->next) {
172 struct ly_in *in;
173 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100174 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200175 ly_in_free(in, 0);
176
177 switch (kw) {
178 case LY_STMT_EXTENSION_INSTANCE:
179 LY_CHECK_RET(lysp_stmt_ext(ctx, child, substmt, LY_ARRAY_COUNT(*qnames) - 1, exts));
180 break;
181 default:
182 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
183 return LY_EVALID;
184 }
185 }
186 return LY_SUCCESS;
187}
188
189/**
Radek Krejci335332a2019-09-05 13:03:35 +0200190 * @brief Parse a generic text field that can have more instances such as base.
191 *
192 * @param[in] ctx yang parser context for logging.
193 * @param[in,out] data Data to read from, always moved to currently handled character.
194 * @param[in] substmt Type of this substatement.
195 * @param[in,out] texts Parsed values to add to.
196 * @param[in] arg Type of the expected argument.
197 * @param[in,out] exts Extension instances to add to.
198 *
199 * @return LY_ERR values.
200 */
201static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200202lysp_stmt_text_fields(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, LYEXT_SUBSTMT substmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200203 const char ***texts, enum yang_arg arg, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200204{
205 const char **item;
206 const struct lysp_stmt *child;
207
208 LY_CHECK_RET(lysp_stmt_validate_value(ctx, arg, stmt->arg));
209
210 /* allocate new pointer */
Michal Vaskob36053d2020-03-26 15:49:30 +0100211 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200212 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, item));
Radek Krejci335332a2019-09-05 13:03:35 +0200213
214 for (child = stmt->child; child; child = child->next) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200215 struct ly_in *in;
216 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100217 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200218 ly_in_free(in, 0);
Radek Krejci335332a2019-09-05 13:03:35 +0200219
220 switch (kw) {
221 case LY_STMT_EXTENSION_INSTANCE:
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200222 LY_CHECK_RET(lysp_stmt_ext(ctx, child, substmt, LY_ARRAY_COUNT(*texts) - 1, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200223 break;
224 default:
225 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
226 return LY_EVALID;
227 }
228 }
229 return LY_SUCCESS;
230}
231
232/**
233 * @brief Parse the status statement.
234 *
235 * @param[in] ctx yang parser context for logging.
236 * @param[in,out] data Data to read from, always moved to currently handled character.
237 * @param[in,out] flags Flags to add to.
238 * @param[in,out] exts Extension instances to add to.
239 *
240 * @return LY_ERR values.
241 */
242static LY_ERR
243lysp_stmt_status(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint16_t *flags, struct lysp_ext_instance **exts)
244{
245 size_t arg_len;
246 const struct lysp_stmt *child;
247
248 if (*flags & LYS_STATUS_MASK) {
249 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
250 return LY_EVALID;
251 }
252
253 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
254 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100255 if ((arg_len == ly_strlen_const("current")) && !strncmp(stmt->arg, "current", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200256 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100257 } else if ((arg_len == ly_strlen_const("deprecated")) && !strncmp(stmt->arg, "deprecated", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200258 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100259 } else if ((arg_len == ly_strlen_const("obsolete")) && !strncmp(stmt->arg, "obsolete", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200260 *flags |= LYS_STATUS_OBSLT;
261 } else {
262 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "status");
263 return LY_EVALID;
264 }
265
266 for (child = stmt->child; child; child = child->next) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200267 struct ly_in *in;
268 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100269 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200270 ly_in_free(in, 0);
Radek Krejci335332a2019-09-05 13:03:35 +0200271
272 switch (kw) {
273 case LY_STMT_EXTENSION_INSTANCE:
274 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LYEXT_SUBSTMT_STATUS, 0, exts));
275 break;
276 default:
277 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
278 return LY_EVALID;
279 }
280 }
281 return LY_SUCCESS;
282}
283
284/**
285 * @brief Parse a restriction such as range or length.
286 *
287 * @param[in] ctx yang parser context for logging.
288 * @param[in,out] data Data to read from, always moved to currently handled character.
289 * @param[in] restr_kw Type of this particular restriction.
290 * @param[in,out] exts Extension instances to add to.
291 *
292 * @return LY_ERR values.
293 */
294static LY_ERR
295lysp_stmt_restr(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt restr_kw, struct lysp_restr *restr)
296{
297 const struct lysp_stmt *child;
298
299 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200300 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200301 restr->arg.mod = ctx->parsed_mod;
Radek Krejci335332a2019-09-05 13:03:35 +0200302
303 for (child = stmt->child; child; child = child->next) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200304 struct ly_in *in;
305 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100306 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200307 ly_in_free(in, 0);
Radek Krejci335332a2019-09-05 13:03:35 +0200308
309 switch (kw) {
310 case LY_STMT_DESCRIPTION:
311 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
312 break;
313 case LY_STMT_REFERENCE:
314 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
315 break;
316 case LY_STMT_ERROR_APP_TAG:
Radek Krejcieccf6602021-02-05 19:42:54 +0100317 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, LYEXT_SUBSTMT_ERROR_APP_TAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200318 break;
319 case LY_STMT_ERROR_MESSAGE:
Radek Krejcieccf6602021-02-05 19:42:54 +0100320 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, LYEXT_SUBSTMT_ERROR_MESSAGE, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200321 break;
322 case LY_STMT_EXTENSION_INSTANCE:
323 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
324 break;
325 default:
326 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
327 return LY_EVALID;
328 }
329 }
330 return LY_SUCCESS;
331}
332
333/**
334 * @brief Parse a restriction that can have more instances such as must.
335 *
336 * @param[in] ctx yang parser context for logging.
337 * @param[in,out] data Data to read from, always moved to currently handled character.
338 * @param[in] restr_kw Type of this particular restriction.
339 * @param[in,out] restrs Restrictions to add to.
340 *
341 * @return LY_ERR values.
342 */
343static LY_ERR
344lysp_stmt_restrs(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt restr_kw, struct lysp_restr **restrs)
345{
346 struct lysp_restr *restr;
347
Michal Vaskob36053d2020-03-26 15:49:30 +0100348 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200349 return lysp_stmt_restr(ctx, stmt, restr_kw, restr);
350}
351
352/**
353 * @brief Parse the value or position statement. Substatement of type enum statement.
354 *
355 * @param[in] ctx yang parser context for logging.
356 * @param[in,out] data Data to read from, always moved to currently handled character.
357 * @param[in] val_kw Type of this particular keyword.
358 * @param[in,out] value Value to write to.
359 * @param[in,out] flags Flags to write to.
360 * @param[in,out] exts Extension instances to add to.
361 *
362 * @return LY_ERR values.
363 */
364static LY_ERR
365lysp_stmt_type_enum_value_pos(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt val_kw, int64_t *value, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +0200366 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200367{
368 size_t arg_len;
369 char *ptr = NULL;
370 long int num = 0;
371 unsigned long int unum = 0;
372 struct lysp_stmt *child;
373
374 if (*flags & LYS_SET_VALUE) {
375 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
376 return LY_EVALID;
377 }
378 *flags |= LYS_SET_VALUE;
379
380 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
381
382 arg_len = strlen(stmt->arg);
383 if (!arg_len || (stmt->arg[0] == '+') || ((stmt->arg[0] == '0') && (arg_len > 1)) || ((val_kw == LY_STMT_POSITION) && !strncmp(stmt->arg, "-0", 2))) {
384 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(val_kw));
385 goto error;
386 }
387
388 errno = 0;
389 if (val_kw == LY_STMT_VALUE) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100390 num = strtol(stmt->arg, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +0200391 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Radek Krejci335332a2019-09-05 13:03:35 +0200392 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(val_kw));
393 goto error;
394 }
395 } else {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100396 unum = strtoul(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200397 if (unum > UINT64_C(4294967295)) {
398 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(val_kw));
399 goto error;
400 }
401 }
402 /* we have not parsed the whole argument */
403 if ((size_t)(ptr - stmt->arg) != arg_len) {
404 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, ly_stmt2str(val_kw));
405 goto error;
406 }
407 if (errno == ERANGE) {
408 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, ly_stmt2str(val_kw));
409 goto error;
410 }
411 if (val_kw == LY_STMT_VALUE) {
412 *value = num;
413 } else {
414 *value = unum;
415 }
416
417 for (child = stmt->child; child; child = child->next) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200418 struct ly_in *in;
419 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100420 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200421 ly_in_free(in, 0);
Radek Krejci335332a2019-09-05 13:03:35 +0200422
423 switch (kw) {
424 case LY_STMT_EXTENSION_INSTANCE:
425 LY_CHECK_RET(lysp_stmt_ext(ctx, child, val_kw == LY_STMT_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts));
426 break;
427 default:
428 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
429 return LY_EVALID;
430 }
431 }
432 return LY_SUCCESS;
433
434error:
435 return LY_EVALID;
436}
437
438/**
439 * @brief Parse the enum or bit statement. Substatement of type statement.
440 *
441 * @param[in] ctx yang parser context for logging.
442 * @param[in,out] data Data to read from, always moved to currently handled character.
443 * @param[in] enum_kw Type of this particular keyword.
444 * @param[in,out] enums Enums or bits to add to.
445 *
446 * @return LY_ERR values.
447 */
448static LY_ERR
449lysp_stmt_type_enum(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt enum_kw, struct lysp_type_enum **enums)
450{
451 struct lysp_type_enum *enm;
452 const struct lysp_stmt *child;
453
454 LY_CHECK_RET(lysp_stmt_validate_value(ctx, enum_kw == LY_STMT_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, stmt->arg));
455
Michal Vaskob36053d2020-03-26 15:49:30 +0100456 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200457
458 if (enum_kw == LY_STMT_ENUM) {
459 LY_CHECK_RET(lysp_check_enum_name(ctx, stmt->arg, strlen(stmt->arg)));
460 } /* else nothing specific for YANG_BIT */
461
Radek Krejci011e4aa2020-09-04 15:22:31 +0200462 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &enm->name));
Radek Krejci335332a2019-09-05 13:03:35 +0200463 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
464
465 for (child = stmt->child; child; child = child->next) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200466 struct ly_in *in;
467 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100468 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200469 ly_in_free(in, 0);
Radek Krejci335332a2019-09-05 13:03:35 +0200470
471 switch (kw) {
472 case LY_STMT_DESCRIPTION:
473 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
474 break;
475 case LY_STMT_IF_FEATURE:
476 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejcieccf6602021-02-05 19:42:54 +0100477 LY_CHECK_RET(lysp_stmt_qnames(ctx, child, LYEXT_SUBSTMT_IF_FEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200478 break;
479 case LY_STMT_REFERENCE:
480 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts));
481 break;
482 case LY_STMT_STATUS:
483 LY_CHECK_RET(lysp_stmt_status(ctx, child, &enm->flags, &enm->exts));
484 break;
485 case LY_STMT_VALUE:
486 LY_CHECK_ERR_RET(enum_kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Michal Vasko69730152020-10-09 16:30:07 +0200487 ly_stmt2str(enum_kw)), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200488 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, kw, &enm->value, &enm->flags, &enm->exts));
489 break;
490 case LY_STMT_POSITION:
491 LY_CHECK_ERR_RET(enum_kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Michal Vasko69730152020-10-09 16:30:07 +0200492 ly_stmt2str(enum_kw)), LY_EVALID);
Radek Krejci335332a2019-09-05 13:03:35 +0200493 LY_CHECK_RET(lysp_stmt_type_enum_value_pos(ctx, child, kw, &enm->value, &enm->flags, &enm->exts));
494 break;
495 case LY_STMT_EXTENSION_INSTANCE:
496 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
497 break;
498 default:
499 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
500 return LY_EVALID;
501 }
502 }
503 return LY_SUCCESS;
504}
505
506/**
507 * @brief Parse the fraction-digits statement. Substatement of type statement.
508 *
509 * @param[in] ctx yang parser context for logging.
510 * @param[in,out] data Data to read from, always moved to currently handled character.
511 * @param[in,out] fracdig Value to write to.
512 * @param[in,out] exts Extension instances to add to.
513 *
514 * @return LY_ERR values.
515 */
516static LY_ERR
517lysp_stmt_type_fracdigits(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *fracdig, struct lysp_ext_instance **exts)
518{
519 char *ptr;
520 size_t arg_len;
521 unsigned long int num;
522 const struct lysp_stmt *child;
523
524 if (*fracdig) {
525 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
526 return LY_EVALID;
527 }
528
529 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
530 arg_len = strlen(stmt->arg);
531 if (!arg_len || (stmt->arg[0] == '0') || !isdigit(stmt->arg[0])) {
532 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
533 return LY_EVALID;
534 }
535
536 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100537 num = strtoul(stmt->arg, &ptr, LY_BASE_DEC);
Radek Krejci335332a2019-09-05 13:03:35 +0200538 /* we have not parsed the whole argument */
539 if ((size_t)(ptr - stmt->arg) != arg_len) {
540 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "fraction-digits");
541 return LY_EVALID;
542 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100543 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200544 LOGVAL_PARSER(ctx, LY_VCODE_OOB, arg_len, stmt->arg, "fraction-digits");
545 return LY_EVALID;
546 }
547 *fracdig = num;
548
549 for (child = stmt->child; child; child = child->next) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200550 struct ly_in *in;
551 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100552 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200553 ly_in_free(in, 0);
Radek Krejci335332a2019-09-05 13:03:35 +0200554
555 switch (kw) {
556 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcieccf6602021-02-05 19:42:54 +0100557 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LYEXT_SUBSTMT_FRACTION_DIGITS, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200558 break;
559 default:
560 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
561 return LY_EVALID;
562 }
563 }
564 return LY_SUCCESS;
565}
566
567/**
568 * @brief Parse the require-instance statement. Substatement of type statement.
569 *
570 * @param[in] ctx yang parser context for logging.
571 * @param[in,out] data Data to read from, always moved to currently handled character.
572 * @param[in,out] reqinst Value to write to.
573 * @param[in,out] flags Flags to write to.
574 * @param[in,out] exts Extension instances to add to.
575 *
576 * @return LY_ERR values.
577 */
578static LY_ERR
579lysp_stmt_type_reqinstance(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, uint8_t *reqinst, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +0200580 struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200581{
582 size_t arg_len;
583 struct lysp_stmt *child;
584
585 if (*flags & LYS_SET_REQINST) {
586 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
587 return LY_EVALID;
588 }
589 *flags |= LYS_SET_REQINST;
590
591 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
592 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100593 if ((arg_len == ly_strlen_const("true")) && !strncmp(stmt->arg, "true", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200594 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100595 } else if ((arg_len != ly_strlen_const("false")) || strncmp(stmt->arg, "false", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200596 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "require-instance");
597 return LY_EVALID;
598 }
599
600 for (child = stmt->child; child; child = child->next) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200601 struct ly_in *in;
602 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100603 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200604 ly_in_free(in, 0);
Radek Krejci335332a2019-09-05 13:03:35 +0200605
606 switch (kw) {
607 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcieccf6602021-02-05 19:42:54 +0100608 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LYEXT_SUBSTMT_REQUIRE_INSTANCE, 0, exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200609 break;
610 default:
611 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
612 return LY_EVALID;
613 }
614 }
615 return LY_SUCCESS;
616}
617
618/**
619 * @brief Parse the modifier statement. Substatement of type pattern statement.
620 *
621 * @param[in] ctx yang parser context for logging.
622 * @param[in,out] data Data to read from, always moved to currently handled character.
623 * @param[in,out] pat Value to write to.
624 * @param[in,out] exts Extension instances to add to.
625 *
626 * @return LY_ERR values.
627 */
628static LY_ERR
629lysp_stmt_type_pattern_modifier(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, const char **pat, struct lysp_ext_instance **exts)
630{
631 size_t arg_len;
632 char *buf;
633 const struct lysp_stmt *child;
634
Radek Krejcif13b87b2020-12-01 22:02:17 +0100635 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
Radek Krejci335332a2019-09-05 13:03:35 +0200636 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
637 return LY_EVALID;
638 }
639
640 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
641 arg_len = strlen(stmt->arg);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100642 if ((arg_len != ly_strlen_const("invert-match")) || strncmp(stmt->arg, "invert-match", arg_len)) {
Radek Krejci335332a2019-09-05 13:03:35 +0200643 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, arg_len, stmt->arg, "modifier");
644 return LY_EVALID;
645 }
646
647 /* replace the value in the dictionary */
648 buf = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100649 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200650 strcpy(buf, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100651 lydict_remove(PARSER_CTX(ctx), *pat);
Radek Krejci335332a2019-09-05 13:03:35 +0200652
Radek Krejcif13b87b2020-12-01 22:02:17 +0100653 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
654 buf[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200655 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Radek Krejci335332a2019-09-05 13:03:35 +0200656
657 for (child = stmt->child; child; child = child->next) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200658 struct ly_in *in;
659 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100660 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200661 ly_in_free(in, 0);
Radek Krejci335332a2019-09-05 13:03:35 +0200662
663 switch (kw) {
664 case LY_STMT_EXTENSION_INSTANCE:
665 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LYEXT_SUBSTMT_MODIFIER, 0, exts));
666 break;
667 default:
668 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
669 return LY_EVALID;
670 }
671 }
672 return LY_SUCCESS;
673}
674
675/**
676 * @brief Parse the pattern statement. Substatement of type statement.
677 *
678 * @param[in] ctx yang parser context for logging.
679 * @param[in,out] data Data to read from, always moved to currently handled character.
680 * @param[in,out] patterns Restrictions to add to.
681 *
682 * @return LY_ERR values.
683 */
684static LY_ERR
685lysp_stmt_type_pattern(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_restr **patterns)
686{
687 char *buf;
688 size_t arg_len;
689 const struct lysp_stmt *child;
690 struct lysp_restr *restr;
691
692 LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
Michal Vaskob36053d2020-03-26 15:49:30 +0100693 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200694 arg_len = strlen(stmt->arg);
695
696 /* add special meaning first byte */
697 buf = malloc(arg_len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100698 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200699 memmove(buf + 1, stmt->arg, arg_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100700 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci335332a2019-09-05 13:03:35 +0200701 buf[arg_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko7f45cf22020-10-01 12:49:44 +0200702 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200703 restr->arg.mod = ctx->parsed_mod;
Radek Krejci335332a2019-09-05 13:03:35 +0200704
705 for (child = stmt->child; child; child = child->next) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200706 struct ly_in *in;
707 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100708 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200709 ly_in_free(in, 0);
Radek Krejci335332a2019-09-05 13:03:35 +0200710
711 switch (kw) {
712 case LY_STMT_DESCRIPTION:
713 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
714 break;
715 case LY_STMT_REFERENCE:
716 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
717 break;
718 case LY_STMT_ERROR_APP_TAG:
Radek Krejcieccf6602021-02-05 19:42:54 +0100719 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, LYEXT_SUBSTMT_ERROR_APP_TAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200720 break;
721 case LY_STMT_ERROR_MESSAGE:
Radek Krejcieccf6602021-02-05 19:42:54 +0100722 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, LYEXT_SUBSTMT_ERROR_MESSAGE, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200723 break;
724 case LY_STMT_MODIFIER:
725 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +0200726 LY_CHECK_RET(lysp_stmt_type_pattern_modifier(ctx, child, &restr->arg.str, &restr->exts));
Radek Krejci335332a2019-09-05 13:03:35 +0200727 break;
728 case LY_STMT_EXTENSION_INSTANCE:
729 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
730 break;
731 default:
732 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
733 return LY_EVALID;
734 }
735 }
736 return LY_SUCCESS;
737}
738
739/**
740 * @brief Parse the type statement.
741 *
742 * @param[in] ctx yang parser context for logging.
743 * @param[in,out] data Data to read from, always moved to currently handled character.
744 * @param[in,out] type Type to wrote to.
745 *
746 * @return LY_ERR values.
747 */
748static LY_ERR
749lysp_stmt_type(struct lys_parser_ctx *ctx, const struct lysp_stmt *stmt, struct lysp_type *type)
750{
751 struct lysp_type *nest_type;
752 const struct lysp_stmt *child;
Radek Krejcib1247842020-07-02 16:22:38 +0200753 const char *str_path = NULL;
Michal Vasko004d3152020-06-11 19:59:22 +0200754 LY_ERR ret;
Radek Krejci335332a2019-09-05 13:03:35 +0200755
756 if (type->name) {
757 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
758 return LY_EVALID;
759 }
Radek Krejci011e4aa2020-09-04 15:22:31 +0200760 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200761 type->pmod = ctx->parsed_mod;
Radek Krejci335332a2019-09-05 13:03:35 +0200762
763 for (child = stmt->child; child; child = child->next) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200764 struct ly_in *in;
765 LY_CHECK_RET(ly_in_new_memory(child->stmt, &in));
Radek Krejcid54412f2020-12-17 20:25:35 +0100766 enum ly_stmt kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200767 ly_in_free(in, 0);
Radek Krejci335332a2019-09-05 13:03:35 +0200768
769 switch (kw) {
770 case LY_STMT_BASE:
771 LY_CHECK_RET(lysp_stmt_text_fields(ctx, child, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
772 type->flags |= LYS_SET_BASE;
773 break;
774 case LY_STMT_BIT:
775 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, kw, &type->bits));
776 type->flags |= LYS_SET_BIT;
777 break;
778 case LY_STMT_ENUM:
779 LY_CHECK_RET(lysp_stmt_type_enum(ctx, child, kw, &type->enums));
780 type->flags |= LYS_SET_ENUM;
781 break;
782 case LY_STMT_FRACTION_DIGITS:
783 LY_CHECK_RET(lysp_stmt_type_fracdigits(ctx, child, &type->fraction_digits, &type->exts));
784 type->flags |= LYS_SET_FRDIGITS;
785 break;
786 case LY_STMT_LENGTH:
787 if (type->length) {
788 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
789 return LY_EVALID;
790 }
791 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100792 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200793
794 LY_CHECK_RET(lysp_stmt_restr(ctx, child, kw, type->length));
795 type->flags |= LYS_SET_LENGTH;
796 break;
797 case LY_STMT_PATH:
Michal Vasko004d3152020-06-11 19:59:22 +0200798 LY_CHECK_RET(lysp_stmt_text_field(ctx, child, LYEXT_SUBSTMT_PATH, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vasko6b26e742020-07-17 15:02:10 +0200799 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
Michal Vasko69730152020-10-09 16:30:07 +0200800 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200801 lydict_remove(PARSER_CTX(ctx), str_path);
802 LY_CHECK_RET(ret);
Radek Krejci335332a2019-09-05 13:03:35 +0200803 type->flags |= LYS_SET_PATH;
804 break;
805 case LY_STMT_PATTERN:
806 LY_CHECK_RET(lysp_stmt_type_pattern(ctx, child, &type->patterns));
807 type->flags |= LYS_SET_PATTERN;
808 break;
809 case LY_STMT_RANGE:
810 if (type->range) {
811 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
812 return LY_EVALID;
813 }
814 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100815 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200816
817 LY_CHECK_RET(lysp_stmt_restr(ctx, child, kw, type->range));
818 type->flags |= LYS_SET_RANGE;
819 break;
820 case LY_STMT_REQUIRE_INSTANCE:
821 LY_CHECK_RET(lysp_stmt_type_reqinstance(ctx, child, &type->require_instance, &type->flags, &type->exts));
822 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
823 break;
824 case LY_STMT_TYPE:
Michal Vaskob36053d2020-03-26 15:49:30 +0100825 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci335332a2019-09-05 13:03:35 +0200826 LY_CHECK_RET(lysp_stmt_type(ctx, child, nest_type));
827 type->flags |= LYS_SET_TYPE;
828 break;
829 case LY_STMT_EXTENSION_INSTANCE:
830 LY_CHECK_RET(lysp_stmt_ext(ctx, child, LYEXT_SUBSTMT_SELF, 0, &type->exts));
831 break;
832 default:
833 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
834 return LY_EVALID;
835 }
836 }
837 return LY_SUCCESS;
838}
839
840LY_ERR
Radek Krejciad5963b2019-09-06 16:03:05 +0200841lysp_stmt_parse(struct lysc_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt kw, void **result, struct lysp_ext_instance **exts)
Radek Krejci335332a2019-09-05 13:03:35 +0200842{
Radek Krejciad5963b2019-09-06 16:03:05 +0200843 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +0100844 struct lys_yang_parser_ctx pctx = {0};
Radek Krejci335332a2019-09-05 13:03:35 +0200845
Michal Vaskob36053d2020-03-26 15:49:30 +0100846 pctx.format = LYS_IN_YANG;
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200847 pctx.parsed_mod = ctx->pmod;
Radek Krejci2efc45b2020-12-22 16:25:44 +0100848
Radek Krejciddace2c2021-01-08 11:30:56 +0100849 LOG_LOCSET(NULL, NULL, ctx->path, NULL);
Radek Krejci335332a2019-09-05 13:03:35 +0200850
Michal Vaskod989ba02020-08-24 10:59:24 +0200851 switch (kw) {
Michal Vasko69730152020-10-09 16:30:07 +0200852 case LY_STMT_STATUS:
Michal Vasko22df3f02020-08-24 13:29:22 +0200853 ret = lysp_stmt_status((struct lys_parser_ctx *)&pctx, stmt, *(uint16_t **)result, exts);
Radek Krejciad5963b2019-09-06 16:03:05 +0200854 break;
Radek Krejci335332a2019-09-05 13:03:35 +0200855 case LY_STMT_TYPE: {
856 struct lysp_type *type;
857 type = calloc(1, sizeof *type);
858
Michal Vaskob36053d2020-03-26 15:49:30 +0100859 ret = lysp_stmt_type((struct lys_parser_ctx *)&pctx, stmt, type);
Radek Krejci335332a2019-09-05 13:03:35 +0200860 (*result) = type;
861 break;
Radek Krejci0f969882020-08-21 16:56:47 +0200862 }
Radek Krejci335332a2019-09-05 13:03:35 +0200863 default:
864 LOGINT(ctx->ctx);
865 return LY_EINT;
866 }
867
Radek Krejciddace2c2021-01-08 11:30:56 +0100868 LOG_LOCBACK(0, 0, 1, 0);
Radek Krejciad5963b2019-09-06 16:03:05 +0200869 return ret;
Radek Krejci335332a2019-09-05 13:03:35 +0200870}