blob: d0b2ea151defca6984d92bb04bdbc69c5ca5666e [file] [log] [blame]
Michal Vasko7fbc8162018-09-17 10:35:16 +02001/**
2 * @file parser_yang.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief YANG parser
5 *
Michal Vaskoc636ea42022-09-16 10:20:31 +02006 * Copyright (c) 2018 - 2022 CESNET, z.s.p.o.
Michal Vasko7fbc8162018-09-17 10:35:16 +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 */
Michal Vasko63f3d842020-07-08 10:10:14 +020014#include "parser_internal.h"
Michal Vasko7fbc8162018-09-17 10:35:16 +020015
Radek Krejcie7b95092019-05-15 11:03:07 +020016#include <assert.h>
17#include <ctype.h>
18#include <errno.h>
19#include <stdint.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
Radek Krejci535ea9f2020-05-29 16:01:05 +020024#include "common.h"
Michal Vasko7fbc8162018-09-17 10:35:16 +020025#include "context.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020026#include "dict.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020027#include "in_internal.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020028#include "log.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020029#include "parser_schema.h"
Michal Vasko69730152020-10-09 16:30:07 +020030#include "path.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020031#include "set.h"
32#include "tree.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010033#include "tree_edit.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020034#include "tree_schema.h"
Michal Vaskoc636ea42022-09-16 10:20:31 +020035#include "tree_schema_free.h"
Radek Krejci70853c52018-10-15 14:46:16 +020036#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020037
Radek Krejci77114102021-03-10 15:21:57 +010038struct lys_glob_unres;
39
Radek Krejciceaf2122019-01-02 15:03:26 +010040/**
41 * @brief Insert WORD into the libyang context's dictionary and store as TARGET.
42 * @param[in] CTX yang parser context to access libyang context.
43 * @param[in] BUF buffer in case the word is not a constant and can be inserted directly (zero-copy)
44 * @param[out] TARGET variable where to store the pointer to the inserted value.
45 * @param[in] WORD string to store.
46 * @param[in] LEN length of the string in WORD to store.
47 */
Michal Vasko12ef5362022-09-16 15:13:58 +020048#define INSERT_WORD_GOTO(CTX, BUF, TARGET, WORD, LEN, RET, LABEL) \
49 if (BUF) {LY_CHECK_GOTO(RET = lydict_insert_zc(PARSER_CTX(CTX), WORD, &(TARGET)), LABEL);}\
50 else {LY_CHECK_GOTO(RET = lydict_insert(PARSER_CTX(CTX), LEN ? WORD : "", LEN, &(TARGET)), LABEL);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020051
Radek Krejciceaf2122019-01-02 15:03:26 +010052/**
Michal Vasko63f3d842020-07-08 10:10:14 +020053 * @brief Read from the IN structure COUNT items. Also updates the indent value in yang parser context
Radek Krejciceaf2122019-01-02 15:03:26 +010054 * @param[in] CTX yang parser context to update its indent value.
Radek Krejciceaf2122019-01-02 15:03:26 +010055 * @param[in] COUNT number of items for which the DATA pointer is supposed to move on.
56 */
Radek Krejcid54412f2020-12-17 20:25:35 +010057#define MOVE_INPUT(CTX, COUNT) ly_in_skip((CTX)->in, COUNT);(CTX)->indent+=COUNT
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020058
Michal Vaskoea5abea2018-09-18 13:10:54 +020059/**
aPieceka24a2252021-05-07 10:52:31 +020060 * @brief Loop through all substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +020061 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020062 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020063 * @param[out] KW YANG keyword read.
64 * @param[out] WORD Pointer to the keyword itself.
65 * @param[out] WORD_LEN Length of the keyword.
Michal Vasko12ef5362022-09-16 15:13:58 +020066 * @param[out] RET Variable for error storing.
aPieceka24a2252021-05-07 10:52:31 +020067 * @param[in] SUC_CMD Command is applied if a semicolon is found, so no
68 * substatements are available. It is expected to contain a return or goto command.
69 * @param[in] ERR_CMD Command is applied if an error occurs before loop through
70 * substatements. It is expected to contain return or goto command.
Michal Vaskoea5abea2018-09-18 13:10:54 +020071 *
72 * @return In case there are no substatements or a fatal error encountered.
73 */
Michal Vasko12ef5362022-09-16 15:13:58 +020074#define YANG_READ_SUBSTMT_FOR(CTX, KW, WORD, WORD_LEN, RET, SUC_CMD, ERR_CMD) \
75 if ((RET = get_keyword(CTX, &KW, &WORD, &WORD_LEN))) { \
aPieceka24a2252021-05-07 10:52:31 +020076 ERR_CMD; \
77 } \
Radek Krejcid6b76452019-09-03 17:03:03 +020078 if (KW == LY_STMT_SYNTAX_SEMICOLON) { \
aPieceka24a2252021-05-07 10:52:31 +020079 SUC_CMD; \
Michal Vasko7fbc8162018-09-17 10:35:16 +020080 } \
Radek Krejcid6b76452019-09-03 17:03:03 +020081 if (KW != LY_STMT_SYNTAX_LEFT_BRACE) { \
David Sedlákb3077192019-06-19 10:55:37 +020082 LOGVAL_PARSER(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko12ef5362022-09-16 15:13:58 +020083 RET = LY_EVALID; \
aPieceka24a2252021-05-07 10:52:31 +020084 ERR_CMD; \
Michal Vasko7fbc8162018-09-17 10:35:16 +020085 } \
Michal Vasko12ef5362022-09-16 15:13:58 +020086 for (RET = get_keyword(CTX, &KW, &WORD, &WORD_LEN); \
87 !RET && (KW != LY_STMT_SYNTAX_RIGHT_BRACE); \
88 RET = get_keyword(CTX, &KW, &WORD, &WORD_LEN))
Michal Vasko7fbc8162018-09-17 10:35:16 +020089
Radek Krejci33090f92020-12-17 20:12:46 +010090LY_ERR parse_container(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent,
Radek Krejci0f969882020-08-21 16:56:47 +020091 struct lysp_node **siblings);
Radek Krejci33090f92020-12-17 20:12:46 +010092LY_ERR parse_uses(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
93LY_ERR parse_choice(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
94LY_ERR parse_case(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
95LY_ERR parse_list(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings);
Radek Krejci2a9fc652021-01-22 17:44:34 +010096LY_ERR parse_grouping(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +020097
Michal Vaskoea5abea2018-09-18 13:10:54 +020098/**
99 * @brief Add another character to dynamic buffer, a low-level function.
100 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200101 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200102 *
Radek Krejci404251e2018-10-09 12:06:44 +0200103 * @param[in] ctx libyang context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200104 * @param[in,out] in Input structure.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200105 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200106 * @param[in,out] buf Buffer to use, can be moved by realloc().
107 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200108 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200109 *
110 * @return LY_ERR values.
111 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200112LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200113buf_add_char(struct ly_ctx *ctx, struct ly_in *in, size_t len, char **buf, size_t *buf_len, size_t *buf_used)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200114{
Radek Krejcif13b87b2020-12-01 22:02:17 +0100115#define BUF_STEP 16;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200116 if (*buf_len <= (*buf_used) + len) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100117 *buf_len += BUF_STEP;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200118 *buf = ly_realloc(*buf, *buf_len);
119 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
120 }
Radek Krejcic0917392019-04-10 13:04:04 +0200121 if (*buf_used) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200122 ly_in_read(in, &(*buf)[*buf_used], len);
Radek Krejcic0917392019-04-10 13:04:04 +0200123 } else {
Michal Vasko63f3d842020-07-08 10:10:14 +0200124 ly_in_read(in, *buf, len);
Radek Krejcic0917392019-04-10 13:04:04 +0200125 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200126
Radek Krejci44ceedc2018-10-02 15:54:31 +0200127 (*buf_used) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200128 return LY_SUCCESS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100129#undef BUF_STEP
Michal Vasko7fbc8162018-09-17 10:35:16 +0200130}
131
Michal Vaskoea5abea2018-09-18 13:10:54 +0200132/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200133 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
134 *
135 * @param[in] ctx yang parser context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200136 * @param[in] arg Type of the input string to select method of checking character validity.
137 * @param[in,out] word_p Word pointer. If buffer (\p word_b) was not yet needed, it is just a pointer to the first
Michal Vaskoea5abea2018-09-18 13:10:54 +0200138 * stored character. If buffer was needed (\p word_b is non-NULL or \p need_buf is set), it is pointing to the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200139 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
140 * @param[in,out] word_b Word buffer. Is kept NULL as long as it is not requested (word is a substring of the data).
Michal Vaskoea5abea2018-09-18 13:10:54 +0200141 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200142 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
David Sedlák40bb13b2019-07-10 14:34:18 +0200143 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
144 * 0 - colon not yet found (no prefix)
145 * 1 - \p c is the colon character
146 * 2 - prefix already processed, now processing the identifier
Michal Vaskoea5abea2018-09-18 13:10:54 +0200147 *
148 * @return LY_ERR values.
149 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200150LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +0100151buf_store_char(struct lys_yang_parser_ctx *ctx, enum yang_arg arg, char **word_p, size_t *word_len,
Radek Krejci857189e2020-09-01 13:26:36 +0200152 char **word_b, size_t *buf_len, ly_bool need_buf, uint8_t *prefix)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200153{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200154 uint32_t c;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200155 size_t len;
156
Radek Krejcif29b7c32019-04-09 16:17:49 +0200157 /* check valid combination of input paremeters - if need_buf specified, word_b must be provided */
158 assert(!need_buf || (need_buf && word_b));
159
Radek Krejci44ceedc2018-10-02 15:54:31 +0200160 /* get UTF8 code point (and number of bytes coding the character) */
Radek Krejci33090f92020-12-17 20:12:46 +0100161 LY_CHECK_ERR_RET(ly_getutf8(&ctx->in->current, &c, &len),
162 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, ctx->in->current[-len]), LY_EVALID);
163 ctx->in->current -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200164 if (c == '\n') {
165 ctx->indent = 0;
Radek Krejcidd713ce2021-01-04 23:12:12 +0100166 LY_IN_NEW_LINE(ctx->in);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200167 } else {
168 /* note - even the multibyte character is count as 1 */
169 ++ctx->indent;
170 }
171
Radek Krejci44ceedc2018-10-02 15:54:31 +0200172 /* check character validity */
173 switch (arg) {
174 case Y_IDENTIF_ARG:
Michal Vaskob36053d2020-03-26 15:49:30 +0100175 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !(*word_len), NULL));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200176 break;
177 case Y_PREF_IDENTIF_ARG:
Michal Vaskob36053d2020-03-26 15:49:30 +0100178 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !(*word_len), prefix));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200179 break;
180 case Y_STR_ARG:
181 case Y_MAYBE_STR_ARG:
Michal Vaskob36053d2020-03-26 15:49:30 +0100182 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200183 break;
184 }
185
Michal Vasko7fbc8162018-09-17 10:35:16 +0200186 if (word_b && *word_b) {
187 /* add another character into buffer */
Radek Krejci33090f92020-12-17 20:12:46 +0100188 if (buf_add_char(PARSER_CTX(ctx), ctx->in, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200189 return LY_EMEM;
190 }
191
192 /* in case of realloc */
193 *word_p = *word_b;
Radek Krejcif29b7c32019-04-09 16:17:49 +0200194 } else if (word_b && need_buf) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200195 /* first time we need a buffer, copy everything read up to now */
196 if (*word_len) {
197 *word_b = malloc(*word_len);
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200198 LY_CHECK_ERR_RET(!*word_b, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200199 *buf_len = *word_len;
200 memcpy(*word_b, *word_p, *word_len);
201 }
202
203 /* add this new character into buffer */
Radek Krejci33090f92020-12-17 20:12:46 +0100204 if (buf_add_char(PARSER_CTX(ctx), ctx->in, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200205 return LY_EMEM;
206 }
207
208 /* in case of realloc */
209 *word_p = *word_b;
210 } else {
211 /* just remember the first character pointer */
212 if (!*word_p) {
Radek Krejci33090f92020-12-17 20:12:46 +0100213 *word_p = (char *)ctx->in->current;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200214 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200215 /* ... and update the word's length */
216 (*word_len) += len;
Radek Krejci33090f92020-12-17 20:12:46 +0100217 ly_in_skip(ctx->in, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200218 }
219
220 return LY_SUCCESS;
221}
222
Michal Vaskoea5abea2018-09-18 13:10:54 +0200223/**
224 * @brief Skip YANG comment in data.
225 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200226 * @param[in] ctx yang parser context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200227 * @param[in] comment Type of the comment to process:
228 * 1 for a one-line comment,
229 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200230 * @return LY_ERR values.
231 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200232LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +0100233skip_comment(struct lys_yang_parser_ctx *ctx, uint8_t comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200234{
Radek Krejcif13b87b2020-12-01 22:02:17 +0100235 /* internal statuses: */
236#define COMMENT_NO 0 /* comment ended */
237#define COMMENT_LINE 1 /* in line comment */
238#define COMMENT_BLOCK 2 /* in block comment */
239#define COMMENT_BLOCK_END 3 /* in block comment with last read character '*' */
240
Radek Krejci33090f92020-12-17 20:12:46 +0100241 while (ctx->in->current[0] && comment) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200242 switch (comment) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100243 case COMMENT_LINE:
Radek Krejci33090f92020-12-17 20:12:46 +0100244 if (ctx->in->current[0] == '\n') {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100245 comment = COMMENT_NO;
Radek Krejcid54412f2020-12-17 20:25:35 +0100246 LY_IN_NEW_LINE(ctx->in);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200247 }
248 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100249 case COMMENT_BLOCK:
Radek Krejci33090f92020-12-17 20:12:46 +0100250 if (ctx->in->current[0] == '*') {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100251 comment = COMMENT_BLOCK_END;
Radek Krejci33090f92020-12-17 20:12:46 +0100252 } else if (ctx->in->current[0] == '\n') {
Radek Krejcid54412f2020-12-17 20:25:35 +0100253 LY_IN_NEW_LINE(ctx->in);
Radek Krejci15c80ca2018-10-09 11:01:31 +0200254 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200255 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100256 case COMMENT_BLOCK_END:
Radek Krejci33090f92020-12-17 20:12:46 +0100257 if (ctx->in->current[0] == '/') {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100258 comment = COMMENT_NO;
Radek Krejci33090f92020-12-17 20:12:46 +0100259 } else if (ctx->in->current[0] != '*') {
260 if (ctx->in->current[0] == '\n') {
Radek Krejcid54412f2020-12-17 20:25:35 +0100261 LY_IN_NEW_LINE(ctx->in);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200262 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100263 comment = COMMENT_BLOCK;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200264 }
265 break;
266 default:
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200267 LOGINT_RET(PARSER_CTX(ctx));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200268 }
269
Radek Krejci33090f92020-12-17 20:12:46 +0100270 if (ctx->in->current[0] == '\n') {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200271 ctx->indent = 0;
272 } else {
273 ++ctx->indent;
274 }
Radek Krejci33090f92020-12-17 20:12:46 +0100275 ++ctx->in->current;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200276 }
277
Radek Krejci33090f92020-12-17 20:12:46 +0100278 if (!ctx->in->current[0] && (comment >= COMMENT_BLOCK)) {
David Sedlákb3077192019-06-19 10:55:37 +0200279 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Unexpected end-of-input, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200280 return LY_EVALID;
281 }
282
283 return LY_SUCCESS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100284
285#undef COMMENT_NO
286#undef COMMENT_LINE
287#undef COMMENT_BLOCK
288#undef COMMENT_BLOCK_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200289}
290
Michal Vaskoea5abea2018-09-18 13:10:54 +0200291/**
292 * @brief Read a quoted string from data.
293 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200294 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200295 * @param[in] arg Type of YANG keyword argument expected.
296 * @param[out] word_p Pointer to the read quoted string.
297 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
298 * set to NULL. Otherwise equal to \p word_p.
299 * @param[out] word_len Length of the read quoted string.
300 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
301 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
302 * indenation in the final quoted string.
303 *
304 * @return LY_ERR values.
305 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200306static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +0100307read_qstring(struct lys_yang_parser_ctx *ctx, enum yang_arg arg, char **word_p, char **word_b,
Radek Krejci0f969882020-08-21 16:56:47 +0200308 size_t *word_len, size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200309{
Radek Krejcif13b87b2020-12-01 22:02:17 +0100310 /* string parsing status: */
311#define STRING_ENDED 0 /* string ended */
312#define STRING_SINGLE_QUOTED 1 /* string with ' */
313#define STRING_DOUBLE_QUOTED 2 /* string with " */
314#define STRING_DOUBLE_QUOTED_ESCAPED 3 /* string with " with last character \ */
315#define STRING_PAUSED_NEXTSTRING 4 /* string finished, now skipping whitespaces looking for + */
316#define STRING_PAUSED_CONTINUE 5 /* string continues after +, skipping whitespaces */
317
Radek Krejci1deb5be2020-08-26 16:43:36 +0200318 uint8_t string;
319 uint64_t block_indent = 0, current_indent = 0;
Radek Krejci857189e2020-09-01 13:26:36 +0200320 ly_bool need_buf = 0;
321 uint8_t prefix = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200322 const char *c;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200323 uint64_t trailing_ws = 0; /* current number of stored trailing whitespace characters */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200324
Radek Krejci33090f92020-12-17 20:12:46 +0100325 if (ctx->in->current[0] == '\"') {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100326 string = STRING_DOUBLE_QUOTED;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200327 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200328 } else {
Radek Krejci33090f92020-12-17 20:12:46 +0100329 assert(ctx->in->current[0] == '\'');
Radek Krejcif13b87b2020-12-01 22:02:17 +0100330 string = STRING_SINGLE_QUOTED;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200331 }
Radek Krejci33090f92020-12-17 20:12:46 +0100332 MOVE_INPUT(ctx, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200333
Radek Krejci33090f92020-12-17 20:12:46 +0100334 while (ctx->in->current[0] && string) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200335 switch (string) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100336 case STRING_SINGLE_QUOTED:
Radek Krejci33090f92020-12-17 20:12:46 +0100337 switch (ctx->in->current[0]) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200338 case '\'':
339 /* string may be finished, but check for + */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100340 string = STRING_PAUSED_NEXTSTRING;
Radek Krejci33090f92020-12-17 20:12:46 +0100341 MOVE_INPUT(ctx, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200342 break;
343 default:
344 /* check and store character */
Radek Krejci33090f92020-12-17 20:12:46 +0100345 LY_CHECK_RET(buf_store_char(ctx, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200346 break;
347 }
348 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100349 case STRING_DOUBLE_QUOTED:
Radek Krejci33090f92020-12-17 20:12:46 +0100350 switch (ctx->in->current[0]) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200351 case '\"':
352 /* string may be finished, but check for + */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100353 string = STRING_PAUSED_NEXTSTRING;
Radek Krejci33090f92020-12-17 20:12:46 +0100354 MOVE_INPUT(ctx, 1);
Radek Krejciff13cd12019-10-25 15:34:24 +0200355 trailing_ws = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200356 break;
357 case '\\':
358 /* special character following */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100359 string = STRING_DOUBLE_QUOTED_ESCAPED;
Radek Krejciff13cd12019-10-25 15:34:24 +0200360
361 /* the backslash sequence is substituted, so we will need a buffer to store the result */
362 need_buf = 1;
363
364 /* move forward to the escaped character */
Radek Krejci33090f92020-12-17 20:12:46 +0100365 ++ctx->in->current;
Radek Krejciff13cd12019-10-25 15:34:24 +0200366
367 /* note that the trailing whitespaces are supposed to be trimmed before substitution of
368 * backslash-escaped characters (RFC 7950, 6.1.3), so we have to zero the trailing whitespaces counter */
369 trailing_ws = 0;
370
371 /* since the backslash-escaped character is handled as first non-whitespace character, stop eating indentation */
372 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200373 break;
374 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200375 if (current_indent < block_indent) {
376 ++current_indent;
Radek Krejci33090f92020-12-17 20:12:46 +0100377 MOVE_INPUT(ctx, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200378 } else {
Michal Vasko90edde42019-11-25 15:25:07 +0100379 /* check and store whitespace character */
Radek Krejci33090f92020-12-17 20:12:46 +0100380 LY_CHECK_RET(buf_store_char(ctx, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko90edde42019-11-25 15:25:07 +0100381 trailing_ws++;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200382 }
383 break;
384 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200385 if (current_indent < block_indent) {
386 assert(need_buf);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100387 current_indent += Y_TAB_SPACES;
388 ctx->indent += Y_TAB_SPACES;
Michal Vaskod989ba02020-08-24 10:59:24 +0200389 for ( ; current_indent > block_indent; --current_indent, --ctx->indent) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200390 /* store leftover spaces from the tab */
Radek Krejci33090f92020-12-17 20:12:46 +0100391 c = ctx->in->current;
392 ctx->in->current = " ";
393 LY_CHECK_RET(buf_store_char(ctx, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
394 ctx->in->current = c;
Michal Vasko90edde42019-11-25 15:25:07 +0100395 trailing_ws++;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200396 }
Radek Krejci33090f92020-12-17 20:12:46 +0100397 ++ctx->in->current;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200398 } else {
Michal Vasko90edde42019-11-25 15:25:07 +0100399 /* check and store whitespace character */
Radek Krejci33090f92020-12-17 20:12:46 +0100400 LY_CHECK_RET(buf_store_char(ctx, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko90edde42019-11-25 15:25:07 +0100401 trailing_ws++;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200402 /* additional characters for indentation - only 1 was count in buf_store_char */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100403 ctx->indent += Y_TAB_SPACES - 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200404 }
405 break;
Michal Vaskoa6ecd0c2021-04-09 11:58:26 +0200406 case '\r':
407 if (ctx->in->current[1] != '\n') {
408 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, ctx->in->current[0]);
409 return LY_EVALID;
410 }
411 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200412 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200413 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200414 /* we will be removing the indents so we need our own buffer */
415 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200416
417 /* remove trailing tabs and spaces */
Radek Krejciff13cd12019-10-25 15:34:24 +0200418 (*word_len) = *word_len - trailing_ws;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200419
Radek Krejciff13cd12019-10-25 15:34:24 +0200420 /* restart indentation */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200421 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200422 }
423
424 /* check and store character */
Radek Krejci33090f92020-12-17 20:12:46 +0100425 LY_CHECK_RET(buf_store_char(ctx, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200426
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200427 /* reset context indentation counter for possible string after this one */
428 ctx->indent = 0;
Radek Krejciff13cd12019-10-25 15:34:24 +0200429 trailing_ws = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200430 break;
431 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200432 /* first non-whitespace character, stop eating indentation */
433 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200434
435 /* check and store character */
Radek Krejci33090f92020-12-17 20:12:46 +0100436 LY_CHECK_RET(buf_store_char(ctx, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Radek Krejciff13cd12019-10-25 15:34:24 +0200437 trailing_ws = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200438 break;
439 }
440 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100441 case STRING_DOUBLE_QUOTED_ESCAPED:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200442 /* string encoded characters */
Radek Krejci33090f92020-12-17 20:12:46 +0100443 c = ctx->in->current;
444 switch (ctx->in->current[0]) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200445 case 'n':
Radek Krejci33090f92020-12-17 20:12:46 +0100446 ctx->in->current = "\n";
Radek Krejcidd713ce2021-01-04 23:12:12 +0100447 /* fix false newline count in buf_store_char() */
448 ctx->in->line--;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200449 break;
450 case 't':
Radek Krejci33090f92020-12-17 20:12:46 +0100451 ctx->in->current = "\t";
Michal Vasko7fbc8162018-09-17 10:35:16 +0200452 break;
453 case '\"':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200454 case '\\':
Michal Vasko63f3d842020-07-08 10:10:14 +0200455 /* ok as is */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200456 break;
457 default:
Michal Vasko63f3d842020-07-08 10:10:14 +0200458 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.",
Radek Krejci33090f92020-12-17 20:12:46 +0100459 ctx->in->current[0]);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200460 return LY_EVALID;
461 }
462
463 /* check and store character */
Radek Krejci33090f92020-12-17 20:12:46 +0100464 LY_CHECK_RET(buf_store_char(ctx, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200465
Radek Krejcif13b87b2020-12-01 22:02:17 +0100466 string = STRING_DOUBLE_QUOTED;
Radek Krejci33090f92020-12-17 20:12:46 +0100467 ctx->in->current = c + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200468 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100469 case STRING_PAUSED_NEXTSTRING:
Radek Krejci33090f92020-12-17 20:12:46 +0100470 switch (ctx->in->current[0]) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200471 case '+':
472 /* string continues */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100473 string = STRING_PAUSED_CONTINUE;
Radek Krejciefd22f62018-09-27 11:47:58 +0200474 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200475 break;
Michal Vaskoa6ecd0c2021-04-09 11:58:26 +0200476 case '\r':
477 if (ctx->in->current[1] != '\n') {
478 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, ctx->in->current[0]);
479 return LY_EVALID;
480 }
481 MOVE_INPUT(ctx, 1);
482 /* fallthrough */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200483 case '\n':
Radek Krejcidd713ce2021-01-04 23:12:12 +0100484 LY_IN_NEW_LINE(ctx->in);
Radek Krejcicb3e6472021-01-06 08:19:01 +0100485 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200486 case ' ':
487 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200488 /* just skip */
489 break;
490 default:
491 /* string is finished */
492 goto string_end;
493 }
Radek Krejci33090f92020-12-17 20:12:46 +0100494 MOVE_INPUT(ctx, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200495 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100496 case STRING_PAUSED_CONTINUE:
Radek Krejci33090f92020-12-17 20:12:46 +0100497 switch (ctx->in->current[0]) {
Michal Vaskoa6ecd0c2021-04-09 11:58:26 +0200498 case '\r':
499 if (ctx->in->current[1] != '\n') {
500 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, ctx->in->current[0]);
501 return LY_EVALID;
502 }
503 MOVE_INPUT(ctx, 1);
504 /* fallthrough */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200505 case '\n':
Radek Krejcidd713ce2021-01-04 23:12:12 +0100506 LY_IN_NEW_LINE(ctx->in);
Radek Krejcicb3e6472021-01-06 08:19:01 +0100507 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200508 case ' ':
509 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200510 /* skip */
511 break;
512 case '\'':
Radek Krejcif13b87b2020-12-01 22:02:17 +0100513 string = STRING_SINGLE_QUOTED;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200514 break;
515 case '\"':
Radek Krejcif13b87b2020-12-01 22:02:17 +0100516 string = STRING_DOUBLE_QUOTED;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200517 break;
518 default:
519 /* it must be quoted again */
David Sedlákb3077192019-06-19 10:55:37 +0200520 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200521 return LY_EVALID;
522 }
Radek Krejci33090f92020-12-17 20:12:46 +0100523 MOVE_INPUT(ctx, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200524 break;
525 default:
526 return LY_EINT;
527 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200528 }
529
530string_end:
Michal Vasko69730152020-10-09 16:30:07 +0200531 if ((arg <= Y_PREF_IDENTIF_ARG) && !(*word_len)) {
Radek Krejci4e199f52019-05-28 09:09:28 +0200532 /* empty identifier */
David Sedlákb3077192019-06-19 10:55:37 +0200533 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Statement argument is required.");
Radek Krejci4e199f52019-05-28 09:09:28 +0200534 return LY_EVALID;
535 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200536 return LY_SUCCESS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100537
538#undef STRING_ENDED
539#undef STRING_SINGLE_QUOTED
540#undef STRING_DOUBLE_QUOTED
541#undef STRING_DOUBLE_QUOTED_ESCAPED
542#undef STRING_PAUSED_NEXTSTRING
543#undef STRING_PAUSED_CONTINUE
Michal Vasko7fbc8162018-09-17 10:35:16 +0200544}
545
Michal Vaskoea5abea2018-09-18 13:10:54 +0200546/**
547 * @brief Get another YANG string from the raw data.
548 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200549 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200550 * @param[in] arg Type of YANG keyword argument expected.
Michal Vaskob68ea142021-04-26 13:46:00 +0200551 * @param[out] flags optional output argument to get flag of the argument's quoting (LYS_*QUOTED - see
552 * [schema node flags](@ref snodeflags))
Michal Vasko2ca70f52018-09-27 11:04:51 +0200553 * @param[out] word_p Pointer to the read string. Can return NULL if \p arg is #Y_MAYBE_STR_ARG.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200554 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
555 * set to NULL. Otherwise equal to \p word_p.
556 * @param[out] word_len Length of the read string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200557 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200558 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200559LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +0100560get_argument(struct lys_yang_parser_ctx *ctx, enum yang_arg arg, uint16_t *flags, char **word_p,
Radek Krejci0f969882020-08-21 16:56:47 +0200561 char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200562{
Michal Vaskob68ea142021-04-26 13:46:00 +0200563 LY_ERR ret;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200564 size_t buf_len = 0;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200565 uint8_t prefix = 0;
Michal Vasko69730152020-10-09 16:30:07 +0200566
Michal Vasko7fbc8162018-09-17 10:35:16 +0200567 /* word buffer - dynamically allocated */
568 *word_b = NULL;
569
570 /* word pointer - just a pointer to data */
571 *word_p = NULL;
572
573 *word_len = 0;
Radek Krejci33090f92020-12-17 20:12:46 +0100574 while (ctx->in->current[0]) {
575 switch (ctx->in->current[0]) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200576 case '\'':
577 case '\"':
578 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200579 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
Radek Krejci33090f92020-12-17 20:12:46 +0100580 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, ctx->in->current,
Michal Vasko69730152020-10-09 16:30:07 +0200581 "unquoted string character, optsep, semicolon or opening brace");
Michal Vaskob68ea142021-04-26 13:46:00 +0200582 ret = LY_EVALID;
583 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200584 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200585 if (flags) {
Radek Krejci33090f92020-12-17 20:12:46 +0100586 (*flags) |= ctx->in->current[0] == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200587 }
Michal Vaskob68ea142021-04-26 13:46:00 +0200588 LY_CHECK_GOTO(ret = read_qstring(ctx, arg, word_p, word_b, word_len, &buf_len), error);
Michal Vasko55a16b92021-09-15 08:51:35 +0200589 if (!*word_p) {
590 /* do not return NULL word */
591 *word_p = "";
592 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200593 goto str_end;
594 case '/':
Radek Krejci33090f92020-12-17 20:12:46 +0100595 if (ctx->in->current[1] == '/') {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200596 /* one-line comment */
Radek Krejci33090f92020-12-17 20:12:46 +0100597 MOVE_INPUT(ctx, 2);
Michal Vaskob68ea142021-04-26 13:46:00 +0200598 LY_CHECK_GOTO(ret = skip_comment(ctx, 1), error);
Radek Krejci33090f92020-12-17 20:12:46 +0100599 } else if (ctx->in->current[1] == '*') {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200600 /* block comment */
Radek Krejci33090f92020-12-17 20:12:46 +0100601 MOVE_INPUT(ctx, 2);
Michal Vaskob68ea142021-04-26 13:46:00 +0200602 LY_CHECK_GOTO(ret = skip_comment(ctx, 2), error);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200603 } else {
604 /* not a comment after all */
Michal Vaskob68ea142021-04-26 13:46:00 +0200605 LY_CHECK_GOTO(ret = buf_store_char(ctx, arg, word_p, word_len, word_b, &buf_len, 0, &prefix), error);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200606 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200607 break;
608 case ' ':
609 if (*word_len) {
610 /* word is finished */
611 goto str_end;
612 }
Radek Krejci33090f92020-12-17 20:12:46 +0100613 MOVE_INPUT(ctx, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200614 break;
615 case '\t':
616 if (*word_len) {
617 /* word is finished */
618 goto str_end;
619 }
620 /* tabs count for 8 spaces */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100621 ctx->indent += Y_TAB_SPACES;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200622
Radek Krejci33090f92020-12-17 20:12:46 +0100623 ++ctx->in->current;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200624 break;
Michal Vaskoa6ecd0c2021-04-09 11:58:26 +0200625 case '\r':
626 if (ctx->in->current[1] != '\n') {
627 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, ctx->in->current[0]);
Michal Vaskob68ea142021-04-26 13:46:00 +0200628 ret = LY_EVALID;
629 goto error;
Michal Vaskoa6ecd0c2021-04-09 11:58:26 +0200630 }
631 MOVE_INPUT(ctx, 1);
632 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200633 case '\n':
634 if (*word_len) {
635 /* word is finished */
636 goto str_end;
637 }
Radek Krejcidd713ce2021-01-04 23:12:12 +0100638 LY_IN_NEW_LINE(ctx->in);
Radek Krejcid54412f2020-12-17 20:25:35 +0100639 MOVE_INPUT(ctx, 1);
640
Michal Vasko7fbc8162018-09-17 10:35:16 +0200641 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200642 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200643 break;
644 case ';':
645 case '{':
646 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
647 /* word is finished */
648 goto str_end;
649 }
650
Radek Krejci33090f92020-12-17 20:12:46 +0100651 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, ctx->in->current, "an argument");
Michal Vaskob68ea142021-04-26 13:46:00 +0200652 ret = LY_EVALID;
653 goto error;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200654 case '}':
655 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
Radek Krejci33090f92020-12-17 20:12:46 +0100656 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, ctx->in->current,
Michal Vasko69730152020-10-09 16:30:07 +0200657 "unquoted string character, optsep, semicolon or opening brace");
Michal Vaskob68ea142021-04-26 13:46:00 +0200658 ret = LY_EVALID;
659 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200660 default:
Michal Vaskob68ea142021-04-26 13:46:00 +0200661 LY_CHECK_GOTO(ret = buf_store_char(ctx, arg, word_p, word_len, word_b, &buf_len, 0, &prefix), error);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200662 break;
663 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200664 }
665
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200666 /* unexpected end of loop */
David Sedlákb3077192019-06-19 10:55:37 +0200667 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Michal Vaskob68ea142021-04-26 13:46:00 +0200668 ret = LY_EVALID;
669 goto error;
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200670
Michal Vasko7fbc8162018-09-17 10:35:16 +0200671str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200672 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200673 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200674 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200675 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200676 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200677 *word_p = *word_b;
678 }
679
680 return LY_SUCCESS;
Michal Vaskob68ea142021-04-26 13:46:00 +0200681
682error:
683 free(*word_b);
684 *word_b = NULL;
685 return ret;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200686}
687
Michal Vaskoea5abea2018-09-18 13:10:54 +0200688/**
689 * @brief Get another YANG keyword from the raw data.
690 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200691 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200692 * @param[out] kw YANG keyword read.
693 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
694 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
695 *
696 * @return LY_ERR values.
697 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200698LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +0100699get_keyword(struct lys_yang_parser_ctx *ctx, enum ly_stmt *kw, char **word_p, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200700{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200701 uint8_t prefix;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200702 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200703 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200704
705 if (word_p) {
706 *word_p = NULL;
707 *word_len = 0;
708 }
709
710 /* first skip "optsep", comments */
Radek Krejci33090f92020-12-17 20:12:46 +0100711 while (ctx->in->current[0]) {
712 switch (ctx->in->current[0]) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200713 case '/':
Radek Krejci33090f92020-12-17 20:12:46 +0100714 if (ctx->in->current[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200715 /* one-line comment */
Radek Krejci33090f92020-12-17 20:12:46 +0100716 MOVE_INPUT(ctx, 2);
717 LY_CHECK_RET(skip_comment(ctx, 1));
718 } else if (ctx->in->current[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200719 /* block comment */
Radek Krejci33090f92020-12-17 20:12:46 +0100720 MOVE_INPUT(ctx, 2);
721 LY_CHECK_RET(skip_comment(ctx, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200722 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200723 /* error - not a comment after all, keyword cannot start with slash */
David Sedlákb3077192019-06-19 10:55:37 +0200724 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
Radek Krejcidcc7b322018-10-11 14:24:02 +0200725 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200726 }
Radek Krejci13028282019-06-11 14:56:48 +0200727 continue;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200728 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200729 /* skip whitespaces (optsep) */
Radek Krejcidd713ce2021-01-04 23:12:12 +0100730 LY_IN_NEW_LINE(ctx->in);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200731 ctx->indent = 0;
732 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200733 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200734 /* skip whitespaces (optsep) */
735 ++ctx->indent;
736 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200737 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200738 /* skip whitespaces (optsep) */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100739 ctx->indent += Y_TAB_SPACES;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200740 break;
Michal Vasko50dcbc22021-03-25 12:21:20 +0100741 case '\r':
742 /* possible CRLF endline */
743 if (ctx->in->current[1] == '\n') {
744 break;
745 }
Radek Krejcid43298b2021-03-25 16:17:15 +0100746 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200747 default:
748 /* either a keyword start or an invalid character */
749 goto keyword_start;
750 }
751
Radek Krejci33090f92020-12-17 20:12:46 +0100752 ly_in_skip(ctx->in, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200753 }
754
755keyword_start:
Radek Krejci33090f92020-12-17 20:12:46 +0100756 word_start = ctx->in->current;
Radek Krejcid54412f2020-12-17 20:25:35 +0100757 *kw = lysp_match_kw(ctx->in, &ctx->indent);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200758
aPiecek93582ed2021-05-25 14:49:06 +0200759 if (*kw == LY_STMT_SYNTAX_SEMICOLON) {
760 goto success;
761 } else if (*kw == LY_STMT_SYNTAX_LEFT_BRACE) {
762 ctx->depth++;
763 if (ctx->depth > LY_MAX_BLOCK_DEPTH) {
Michal Vasko8a67eff2021-12-07 14:04:47 +0100764 LOGERR(PARSER_CTX(ctx), LY_EINVAL, "The maximum number of block nestings has been exceeded.");
aPiecek93582ed2021-05-25 14:49:06 +0200765 return LY_EINVAL;
766 }
767 goto success;
768 } else if (*kw == LY_STMT_SYNTAX_RIGHT_BRACE) {
769 ctx->depth--;
Radek Krejci626df482018-10-11 15:06:31 +0200770 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200771 }
772
Radek Krejcid6b76452019-09-03 17:03:03 +0200773 if (*kw != LY_STMT_NONE) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200774 /* make sure we have the whole keyword */
Radek Krejci33090f92020-12-17 20:12:46 +0100775 switch (ctx->in->current[0]) {
Michal Vaskoa6ecd0c2021-04-09 11:58:26 +0200776 case '\r':
777 if (ctx->in->current[1] != '\n') {
778 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, ctx->in->current[0]);
779 return LY_EVALID;
780 }
781 MOVE_INPUT(ctx, 1);
782 /* fallthrough */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200783 case '\n':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200784 case '\t':
Radek Krejciabdd8062019-06-11 16:44:19 +0200785 case ' ':
786 /* mandatory "sep" is just checked, not eaten so nothing in the context is updated */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200787 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200788 case ':':
789 /* keyword is not actually a keyword, but prefix of an extension.
790 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
791 * and we will be checking the keyword (extension instance) itself */
792 prefix = 1;
Radek Krejci33090f92020-12-17 20:12:46 +0100793 MOVE_INPUT(ctx, 1);
Radek Krejci156ccaf2018-10-15 15:49:17 +0200794 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200795 case '{':
796 /* allowed only for input and output statements which can be without arguments */
Michal Vasko69730152020-10-09 16:30:07 +0200797 if ((*kw == LY_STMT_INPUT) || (*kw == LY_STMT_OUTPUT)) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200798 break;
799 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100800 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200801 default:
Radek Krejci33090f92020-12-17 20:12:46 +0100802 MOVE_INPUT(ctx, 1);
803 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(ctx->in->current - word_start), word_start,
Michal Vasko69730152020-10-09 16:30:07 +0200804 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200805 return LY_EVALID;
806 }
807 } else {
808 /* still can be an extension */
809 prefix = 0;
Michal Vaskoa6ecd0c2021-04-09 11:58:26 +0200810
Radek Krejci156ccaf2018-10-15 15:49:17 +0200811extension:
Radek Krejcid54412f2020-12-17 20:25:35 +0100812 while (ctx->in->current[0] && (ctx->in->current[0] != ' ') && (ctx->in->current[0] != '\t') &&
Michal Vaskoa6ecd0c2021-04-09 11:58:26 +0200813 (ctx->in->current[0] != '\n') && (ctx->in->current[0] != '\r') && (ctx->in->current[0] != '{') &&
814 (ctx->in->current[0] != ';')) {
Radek Krejci1deb5be2020-08-26 16:43:36 +0200815 uint32_t c = 0;
816
Radek Krejci33090f92020-12-17 20:12:46 +0100817 LY_CHECK_ERR_RET(ly_getutf8(&ctx->in->current, &c, &len),
818 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, ctx->in->current[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200819 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200820 /* check character validity */
Michal Vasko63f3d842020-07-08 10:10:14 +0200821 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c,
Radek Krejci33090f92020-12-17 20:12:46 +0100822 ctx->in->current - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200823 }
Radek Krejci33090f92020-12-17 20:12:46 +0100824 if (!ctx->in->current[0]) {
David Sedlákb3077192019-06-19 10:55:37 +0200825 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200826 return LY_EVALID;
827 }
828
829 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200830 if (prefix != 2) {
Radek Krejci33090f92020-12-17 20:12:46 +0100831 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(ctx->in->current - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200832 return LY_EVALID;
833 }
834
Radek Krejcid6b76452019-09-03 17:03:03 +0200835 *kw = LY_STMT_EXTENSION_INSTANCE;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200836 }
Michal Vaskoa6ecd0c2021-04-09 11:58:26 +0200837
Radek Krejci626df482018-10-11 15:06:31 +0200838success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200839 if (word_p) {
840 *word_p = (char *)word_start;
Radek Krejci33090f92020-12-17 20:12:46 +0100841 *word_len = ctx->in->current - word_start;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200842 }
843
844 return LY_SUCCESS;
845}
846
Michal Vaskoea5abea2018-09-18 13:10:54 +0200847/**
848 * @brief Parse extension instance substatements.
849 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200850 * @param[in] ctx yang parser context for logging.
Radek Krejci335332a2019-09-05 13:03:35 +0200851 * @param[in] kw Statement keyword value matching @p word value.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200852 * @param[in] word Extension instance substatement name (keyword).
853 * @param[in] word_len Extension instance substatement name length.
854 * @param[in,out] child Children of this extension instance to add to.
855 *
856 * @return LY_ERR values.
857 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200858static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +0100859parse_ext_substmt(struct lys_yang_parser_ctx *ctx, enum ly_stmt kw, char *word, size_t word_len,
Radek Krejci0f969882020-08-21 16:56:47 +0200860 struct lysp_stmt **child)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200861{
862 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100863 LY_ERR ret = LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200864 enum ly_stmt child_kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200865 struct lysp_stmt *stmt, *par_child;
866
867 stmt = calloc(1, sizeof *stmt);
868 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
869
Radek Krejcibb9b1982019-04-08 14:24:59 +0200870 /* insert into parent statements */
871 if (!*child) {
872 *child = stmt;
873 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +0200874 for (par_child = *child; par_child->next; par_child = par_child->next) {}
Radek Krejcibb9b1982019-04-08 14:24:59 +0200875 par_child->next = stmt;
876 }
877
Michal Vaskofc2cd072021-02-24 13:17:17 +0100878 /* statement */
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200879 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), word, word_len, &stmt->stmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200880
881 /* get optional argument */
Radek Krejci33090f92020-12-17 20:12:46 +0100882 LY_CHECK_RET(get_argument(ctx, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
Radek Krejci0ae092d2018-09-20 16:43:19 +0200883 if (word) {
Michal Vasko12ef5362022-09-16 15:13:58 +0200884 INSERT_WORD_GOTO(ctx, buf, stmt->arg, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200885 }
886
Radek Krejci8df109d2021-04-23 12:19:08 +0200887 stmt->format = LY_VALUE_SCHEMA;
Michal Vasko8a67eff2021-12-07 14:04:47 +0100888 stmt->prefix_data = PARSER_CUR_PMOD(ctx);
Michal Vaskofc2cd072021-02-24 13:17:17 +0100889 stmt->kw = kw;
890
aPieceka24a2252021-05-07 10:52:31 +0200891 YANG_READ_SUBSTMT_FOR(ctx, child_kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Radek Krejci33090f92020-12-17 20:12:46 +0100892 LY_CHECK_RET(parse_ext_substmt(ctx, child_kw, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200893 }
Michal Vasko12ef5362022-09-16 15:13:58 +0200894
895cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200896 return ret;
897}
898
Michal Vaskoea5abea2018-09-18 13:10:54 +0200899/**
900 * @brief Parse extension instance.
901 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200902 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200903 * @param[in] ext_name Extension instance substatement name (keyword).
904 * @param[in] ext_name_len Extension instance substatement name length.
Radek Krejcifc596f92021-02-26 22:40:26 +0100905 * @param[in] insubstmt The statement this extension instance is a substatement of.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200906 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
907 * @param[in,out] exts Extension instances to add to.
908 *
909 * @return LY_ERR values.
910 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200911static LY_ERR
Radek Krejcifc596f92021-02-26 22:40:26 +0100912parse_ext(struct lys_yang_parser_ctx *ctx, const char *ext_name, size_t ext_name_len, enum ly_stmt insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200913 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200914{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100915 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200916 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200917 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200918 struct lysp_ext_instance *e;
Radek Krejcid6b76452019-09-03 17:03:03 +0200919 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200920
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200921 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200922
Michal Vaskofc2cd072021-02-24 13:17:17 +0100923 if (!ly_strnchr(ext_name, ':', ext_name_len)) {
924 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%*.s\" without the mandatory prefix.", ext_name_len, ext_name);
925 return LY_EVALID;
926 }
927
928 /* store name */
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200929 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), ext_name, ext_name_len, &e->name));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200930
931 /* get optional argument */
Radek Krejci33090f92020-12-17 20:12:46 +0100932 LY_CHECK_RET(get_argument(ctx, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0ae092d2018-09-20 16:43:19 +0200933 if (word) {
Michal Vasko12ef5362022-09-16 15:13:58 +0200934 INSERT_WORD_GOTO(ctx, buf, e->argument, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200935 }
936
Michal Vaskofc2cd072021-02-24 13:17:17 +0100937 /* store the rest of information */
Radek Krejci8df109d2021-04-23 12:19:08 +0200938 e->format = LY_VALUE_SCHEMA;
aPiecek60d9d672021-04-27 15:49:57 +0200939 e->parsed = NULL;
Michal Vasko8a67eff2021-12-07 14:04:47 +0100940 e->prefix_data = PARSER_CUR_PMOD(ctx);
Radek Krejciab430862021-03-02 20:13:40 +0100941 e->parent_stmt = insubstmt;
942 e->parent_stmt_index = insubstmt_index;
Michal Vaskofc2cd072021-02-24 13:17:17 +0100943
aPieceka24a2252021-05-07 10:52:31 +0200944 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Radek Krejci33090f92020-12-17 20:12:46 +0100945 LY_CHECK_RET(parse_ext_substmt(ctx, kw, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200946 }
Michal Vasko12ef5362022-09-16 15:13:58 +0200947
948cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200949 return ret;
950}
951
Michal Vaskoea5abea2018-09-18 13:10:54 +0200952/**
953 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
954 * description, etc...
955 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200956 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200957 * @param[in] substmt Type of this substatement.
958 * @param[in] substmt_index Index of this substatement.
959 * @param[in,out] value Place to store the parsed value.
960 * @param[in] arg Type of the YANG keyword argument (of the value).
961 * @param[in,out] exts Extension instances to add to.
962 *
963 * @return LY_ERR values.
964 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200965static LY_ERR
Radek Krejcifc596f92021-02-26 22:40:26 +0100966parse_text_field(struct lys_yang_parser_ctx *ctx, enum ly_stmt substmt, uint32_t substmt_index,
Radek Krejci0f969882020-08-21 16:56:47 +0200967 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200968{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100969 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200970 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200971 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200972 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200973
974 if (*value) {
Radek Krejci3972b332021-03-02 16:34:31 +0100975 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200976 return LY_EVALID;
977 }
978
979 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +0100980 LY_CHECK_RET(get_argument(ctx, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200981
982 /* store value and spend buf if allocated */
Michal Vasko12ef5362022-09-16 15:13:58 +0200983 INSERT_WORD_GOTO(ctx, buf, *value, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200984
aPieceka24a2252021-05-07 10:52:31 +0200985 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200986 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200987 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci33090f92020-12-17 20:12:46 +0100988 LY_CHECK_RET(parse_ext(ctx, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200989 break;
990 default:
Radek Krejci3972b332021-03-02 16:34:31 +0100991 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200992 return LY_EVALID;
993 }
994 }
Michal Vasko12ef5362022-09-16 15:13:58 +0200995
996cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200997 return ret;
998}
999
Michal Vaskoea5abea2018-09-18 13:10:54 +02001000/**
1001 * @brief Parse the yang-version statement.
1002 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001003 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001004 * @param[out] version Storage for the parsed information.
Michal Vasko63f3d842020-07-08 10:10:14 +02001005 * @param[in,out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001006 *
1007 * @return LY_ERR values.
1008 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001009static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001010parse_yangversion(struct lys_yang_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001011{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001012 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001013 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001014 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001015 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001016
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001017 if (*version) {
David Sedlákb3077192019-06-19 10:55:37 +02001018 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001019 return LY_EVALID;
1020 }
1021
1022 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001023 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001024
Radek Krejci96e48da2020-09-04 13:18:06 +02001025 if ((word_len == 1) && !strncmp(word, "1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001026 *version = LYS_VERSION_1_0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001027 } else if ((word_len == ly_strlen_const("1.1")) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001028 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001029 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001030 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001031 free(buf);
1032 return LY_EVALID;
1033 }
1034 free(buf);
1035
aPieceka24a2252021-05-07 10:52:31 +02001036 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001037 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001038 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001039 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_YANG_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001040 break;
1041 default:
David Sedlákb3077192019-06-19 10:55:37 +02001042 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001043 return LY_EVALID;
1044 }
1045 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001046 return ret;
1047}
1048
Michal Vaskoea5abea2018-09-18 13:10:54 +02001049/**
1050 * @brief Parse the belongs-to statement.
1051 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001052 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001053 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1054 * @param[in,out] exts Extension instances to add to.
1055 *
1056 * @return LY_ERR values.
1057 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001058static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001059parse_belongsto(struct lys_yang_parser_ctx *ctx, const char **prefix, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001060{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001061 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001062 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001063 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001064 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001065
Michal Vaskoc3781c32020-10-06 14:04:08 +02001066 if (*prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02001067 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001068 return LY_EVALID;
1069 }
1070
Michal Vaskoc3781c32020-10-06 14:04:08 +02001071 /* get value, it must match the main module */
Radek Krejci33090f92020-12-17 20:12:46 +01001072 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001073 if (ly_strncmp(PARSER_CUR_PMOD(ctx)->mod->name, word, word_len)) {
Michal Vaskoc3781c32020-10-06 14:04:08 +02001074 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Submodule \"belongs-to\" value \"%.*s\" does not match its module name \"%s\".",
Michal Vasko8a67eff2021-12-07 14:04:47 +01001075 (int)word_len, word, PARSER_CUR_PMOD(ctx)->mod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02001076 free(buf);
1077 return LY_EVALID;
1078 }
1079 free(buf);
Radek Krejcif09e4e82019-06-14 15:08:11 +02001080
aPieceka24a2252021-05-07 10:52:31 +02001081 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001082 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001083 case LY_STMT_PREFIX:
Radek Krejcifc596f92021-02-26 22:40:26 +01001084 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001085 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001086 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001087 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_BELONGS_TO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001088 break;
1089 default:
David Sedlákb3077192019-06-19 10:55:37 +02001090 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001091 return LY_EVALID;
1092 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001093 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001094 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001095checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001096 /* mandatory substatements */
1097 if (!*prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02001098 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001099 return LY_EVALID;
1100 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001101 return ret;
1102}
1103
Michal Vaskoea5abea2018-09-18 13:10:54 +02001104/**
1105 * @brief Parse the revision-date statement.
1106 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001107 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001108 * @param[in,out] rev Array to store the parsed value in.
1109 * @param[in,out] exts Extension instances to add to.
1110 *
1111 * @return LY_ERR values.
1112 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001113static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001114parse_revisiondate(struct lys_yang_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001115{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001116 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001117 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001118 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001119 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001120
1121 if (rev[0]) {
David Sedlákb3077192019-06-19 10:55:37 +02001122 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001123 return LY_EVALID;
1124 }
1125
1126 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001127 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001128
1129 /* check value */
Michal Vaskob36053d2020-03-26 15:49:30 +01001130 if (lysp_check_date((struct lys_parser_ctx *)ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001131 free(buf);
1132 return LY_EVALID;
1133 }
1134
1135 /* store value and spend buf if allocated */
1136 strncpy(rev, word, word_len);
1137 free(buf);
1138
aPieceka24a2252021-05-07 10:52:31 +02001139 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001140 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001141 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001142 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_REVISION_DATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001143 break;
1144 default:
David Sedlákb3077192019-06-19 10:55:37 +02001145 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001146 return LY_EVALID;
1147 }
1148 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001149 return ret;
1150}
1151
Michal Vaskoea5abea2018-09-18 13:10:54 +02001152/**
1153 * @brief Parse the include statement.
1154 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001155 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001156 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001157 * @param[in,out] includes Parsed includes to add to.
1158 *
1159 * @return LY_ERR values.
1160 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001161static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001162parse_include(struct lys_yang_parser_ctx *ctx, const char *module_name, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001163{
Radek Krejcid33273d2018-10-25 14:55:52 +02001164 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001165 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001166 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001167 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001168 struct lysp_include *inc;
1169
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001170 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001171
1172 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001173 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001174
Michal Vasko12ef5362022-09-16 15:13:58 +02001175 INSERT_WORD_GOTO(ctx, buf, inc->name, word, word_len, ret, cleanup);
Radek Krejci086c7132018-10-26 15:29:04 +02001176
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001177 /* submodules share the namespace with the module names, so there must not be
1178 * a module of the same name in the context, no need for revision matching */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001179 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(PARSER_CTX(ctx), inc->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01001180 LOGVAL_PARSER(ctx, LY_VCODE_NAME2_COL, "module", "submodule", inc->name);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001181 return LY_EVALID;
1182 }
1183
aPieceka24a2252021-05-07 10:52:31 +02001184 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001185 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001186 case LY_STMT_DESCRIPTION:
Radek Krejci335332a2019-09-05 13:03:35 +02001187 PARSER_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejcifc596f92021-02-26 22:40:26 +01001188 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001190 case LY_STMT_REFERENCE:
Radek Krejci335332a2019-09-05 13:03:35 +02001191 PARSER_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejcifc596f92021-02-26 22:40:26 +01001192 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001193 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001194 case LY_STMT_REVISION_DATE:
Radek Krejci33090f92020-12-17 20:12:46 +01001195 LY_CHECK_RET(parse_revisiondate(ctx, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001196 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001197 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001198 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_INCLUDE, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001199 break;
1200 default:
David Sedlákb3077192019-06-19 10:55:37 +02001201 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001202 return LY_EVALID;
1203 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001204 }
Michal Vasko12ef5362022-09-16 15:13:58 +02001205
1206cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001207 return ret;
1208}
1209
Michal Vaskoea5abea2018-09-18 13:10:54 +02001210/**
1211 * @brief Parse the import statement.
1212 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001213 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001214 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001215 * @param[in,out] imports Parsed imports to add to.
1216 *
1217 * @return LY_ERR values.
1218 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001219static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001220parse_import(struct lys_yang_parser_ctx *ctx, const char *module_prefix, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001221{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001222 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001223 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001224 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001225 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001226 struct lysp_import *imp;
1227
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001228 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001229
1230 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001231 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02001232 INSERT_WORD_GOTO(ctx, buf, imp->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001233
aPieceka24a2252021-05-07 10:52:31 +02001234 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001235 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001236 case LY_STMT_PREFIX:
Radek Krejcifc596f92021-02-26 22:40:26 +01001237 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
Michal Vaskob36053d2020-03-26 15:49:30 +01001238 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001239 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001240 case LY_STMT_DESCRIPTION:
Radek Krejci335332a2019-09-05 13:03:35 +02001241 PARSER_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejcifc596f92021-02-26 22:40:26 +01001242 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001243 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001244 case LY_STMT_REFERENCE:
Radek Krejci335332a2019-09-05 13:03:35 +02001245 PARSER_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejcifc596f92021-02-26 22:40:26 +01001246 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001247 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001248 case LY_STMT_REVISION_DATE:
Radek Krejci33090f92020-12-17 20:12:46 +01001249 LY_CHECK_RET(parse_revisiondate(ctx, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001250 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001251 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001252 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_IMPORT, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001253 break;
1254 default:
David Sedlákb3077192019-06-19 10:55:37 +02001255 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001256 return LY_EVALID;
1257 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001258 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001259 LY_CHECK_RET(ret);
Michal Vasko12ef5362022-09-16 15:13:58 +02001260
Radek Krejci6d6556c2018-11-08 09:37:45 +01001261checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001262 /* mandatory substatements */
David Sedlákb3077192019-06-19 10:55:37 +02001263 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001264
Michal Vasko12ef5362022-09-16 15:13:58 +02001265cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001266 return ret;
1267}
1268
Michal Vaskoea5abea2018-09-18 13:10:54 +02001269/**
1270 * @brief Parse the revision statement.
1271 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001272 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001273 * @param[in,out] revs Parsed revisions to add to.
1274 *
1275 * @return LY_ERR values.
1276 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001277static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001278parse_revision(struct lys_yang_parser_ctx *ctx, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001279{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001280 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001281 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001282 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001283 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001284 struct lysp_revision *rev;
1285
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001286 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001287
1288 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001289 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001290
1291 /* check value */
Michal Vaskob36053d2020-03-26 15:49:30 +01001292 if (lysp_check_date((struct lys_parser_ctx *)ctx, word, word_len, "revision")) {
David Sedlák68ef3dc2019-07-22 13:40:19 +02001293 free(buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001294 return LY_EVALID;
1295 }
1296
Radek Krejcib7db73a2018-10-24 14:18:40 +02001297 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001298 free(buf);
1299
aPieceka24a2252021-05-07 10:52:31 +02001300 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001301 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001302 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01001303 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001304 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001305 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001306 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001307 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001308 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001309 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_REVISION, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001310 break;
1311 default:
David Sedlákb3077192019-06-19 10:55:37 +02001312 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001313 return LY_EVALID;
1314 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001315 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001316 return ret;
1317}
1318
Michal Vaskoea5abea2018-09-18 13:10:54 +02001319/**
1320 * @brief Parse a generic text field that can have more instances such as base.
1321 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001322 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001323 * @param[in] substmt Type of this substatement.
1324 * @param[in,out] texts Parsed values to add to.
1325 * @param[in] arg Type of the expected argument.
1326 * @param[in,out] exts Extension instances to add to.
1327 *
1328 * @return LY_ERR values.
1329 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001330static LY_ERR
Radek Krejcifc596f92021-02-26 22:40:26 +01001331parse_text_fields(struct lys_yang_parser_ctx *ctx, enum ly_stmt substmt, const char ***texts, enum yang_arg arg,
Radek Krejci0f969882020-08-21 16:56:47 +02001332 struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001333{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001334 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001335 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001336 const char **item;
1337 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001338 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001339
1340 /* allocate new pointer */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001341 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001342
1343 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001344 LY_CHECK_RET(get_argument(ctx, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001345
Michal Vasko12ef5362022-09-16 15:13:58 +02001346 INSERT_WORD_GOTO(ctx, buf, *item, word, word_len, ret, cleanup);
aPieceka24a2252021-05-07 10:52:31 +02001347 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001348 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001349 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci33090f92020-12-17 20:12:46 +01001350 LY_CHECK_RET(parse_ext(ctx, word, word_len, substmt, LY_ARRAY_COUNT(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001351 break;
1352 default:
Radek Krejci3972b332021-03-02 16:34:31 +01001353 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001354 return LY_EVALID;
1355 }
1356 }
Michal Vasko12ef5362022-09-16 15:13:58 +02001357
1358cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001359 return ret;
1360}
1361
Michal Vaskoea5abea2018-09-18 13:10:54 +02001362/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02001363 * @brief Parse a generic text field that can have more instances such as base.
1364 *
1365 * @param[in] ctx yang parser context for logging.
Michal Vasko7f45cf22020-10-01 12:49:44 +02001366 * @param[in] substmt Type of this substatement.
1367 * @param[in,out] qnames Parsed qnames to add to.
1368 * @param[in] arg Type of the expected argument.
1369 * @param[in,out] exts Extension instances to add to.
1370 *
1371 * @return LY_ERR values.
1372 */
1373static LY_ERR
Radek Krejcifc596f92021-02-26 22:40:26 +01001374parse_qnames(struct lys_yang_parser_ctx *ctx, enum ly_stmt substmt, struct lysp_qname **qnames,
Michal Vasko7f45cf22020-10-01 12:49:44 +02001375 enum yang_arg arg, struct lysp_ext_instance **exts)
1376{
1377 LY_ERR ret = LY_SUCCESS;
1378 char *buf, *word;
1379 struct lysp_qname *item;
1380 size_t word_len;
1381 enum ly_stmt kw;
1382
1383 /* allocate new pointer */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001384 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001385
1386 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001387 LY_CHECK_RET(get_argument(ctx, arg, NULL, &word, &buf, &word_len));
Michal Vasko7f45cf22020-10-01 12:49:44 +02001388
Michal Vasko12ef5362022-09-16 15:13:58 +02001389 INSERT_WORD_GOTO(ctx, buf, item->str, word, word_len, ret, cleanup);
Michal Vasko8a67eff2021-12-07 14:04:47 +01001390 item->mod = PARSER_CUR_PMOD(ctx);
aPieceka24a2252021-05-07 10:52:31 +02001391 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02001392 switch (kw) {
1393 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci33090f92020-12-17 20:12:46 +01001394 LY_CHECK_RET(parse_ext(ctx, word, word_len, substmt, LY_ARRAY_COUNT(*qnames) - 1, exts));
Michal Vasko7f45cf22020-10-01 12:49:44 +02001395 break;
1396 default:
Radek Krejci3972b332021-03-02 16:34:31 +01001397 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(substmt));
Michal Vasko7f45cf22020-10-01 12:49:44 +02001398 return LY_EVALID;
1399 }
1400 }
Michal Vasko12ef5362022-09-16 15:13:58 +02001401
1402cleanup:
Michal Vasko7f45cf22020-10-01 12:49:44 +02001403 return ret;
1404}
1405
1406/**
Michal Vaskoea5abea2018-09-18 13:10:54 +02001407 * @brief Parse the config statement.
1408 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001409 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001410 * @param[in,out] flags Flags to add to.
1411 * @param[in,out] exts Extension instances to add to.
1412 *
1413 * @return LY_ERR values.
1414 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001415static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001416parse_config(struct lys_yang_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001417{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001418 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001419 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001420 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001421 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001422
1423 if (*flags & LYS_CONFIG_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001424 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001425 return LY_EVALID;
1426 }
1427
1428 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001429 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001430
Radek Krejcif13b87b2020-12-01 22:02:17 +01001431 if ((word_len == ly_strlen_const("true")) && !strncmp(word, "true", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001432 *flags |= LYS_CONFIG_W;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001433 } else if ((word_len == ly_strlen_const("false")) && !strncmp(word, "false", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001434 *flags |= LYS_CONFIG_R;
1435 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001436 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001437 free(buf);
1438 return LY_EVALID;
1439 }
1440 free(buf);
1441
aPieceka24a2252021-05-07 10:52:31 +02001442 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001443 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001444 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001445 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001446 break;
1447 default:
David Sedlákb3077192019-06-19 10:55:37 +02001448 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001449 return LY_EVALID;
1450 }
1451 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001452 return ret;
1453}
1454
Michal Vaskoea5abea2018-09-18 13:10:54 +02001455/**
1456 * @brief Parse the mandatory statement.
1457 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001458 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001459 * @param[in,out] flags Flags to add to.
1460 * @param[in,out] exts Extension instances to add to.
1461 *
1462 * @return LY_ERR values.
1463 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001464static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001465parse_mandatory(struct lys_yang_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001466{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001467 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001468 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001469 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001470 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001471
1472 if (*flags & LYS_MAND_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001473 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001474 return LY_EVALID;
1475 }
1476
1477 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001478 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001479
Radek Krejcif13b87b2020-12-01 22:02:17 +01001480 if ((word_len == ly_strlen_const("true")) && !strncmp(word, "true", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001481 *flags |= LYS_MAND_TRUE;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001482 } else if ((word_len == ly_strlen_const("false")) && !strncmp(word, "false", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001483 *flags |= LYS_MAND_FALSE;
1484 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001485 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001486 free(buf);
1487 return LY_EVALID;
1488 }
1489 free(buf);
1490
aPieceka24a2252021-05-07 10:52:31 +02001491 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001492 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001493 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001494 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001495 break;
1496 default:
David Sedlákb3077192019-06-19 10:55:37 +02001497 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001498 return LY_EVALID;
1499 }
1500 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001501 return ret;
1502}
1503
Michal Vaskoea5abea2018-09-18 13:10:54 +02001504/**
1505 * @brief Parse a restriction such as range or length.
1506 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001507 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001508 * @param[in] restr_kw Type of this particular restriction.
1509 * @param[in,out] exts Extension instances to add to.
1510 *
1511 * @return LY_ERR values.
1512 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001513static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001514parse_restr(struct lys_yang_parser_ctx *ctx, enum ly_stmt restr_kw, struct lysp_restr *restr)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001515{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001516 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001517 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001518 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001519 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001520
1521 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001522 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001523
Michal Vaskob36053d2020-03-26 15:49:30 +01001524 CHECK_NONEMPTY(ctx, word_len, ly_stmt2str(restr_kw));
Michal Vasko12ef5362022-09-16 15:13:58 +02001525 INSERT_WORD_GOTO(ctx, buf, restr->arg.str, word, word_len, ret, cleanup);
Michal Vasko8a67eff2021-12-07 14:04:47 +01001526 restr->arg.mod = PARSER_CUR_PMOD(ctx);
aPieceka24a2252021-05-07 10:52:31 +02001527 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001528 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001529 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01001530 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001531 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001532 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001533 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001534 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001535 case LY_STMT_ERROR_APP_TAG:
Radek Krejcifc596f92021-02-26 22:40:26 +01001536 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_ERROR_APP_TAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001537 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001538 case LY_STMT_ERROR_MESSAGE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001539 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_ERROR_MESSAGE, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001540 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001541 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001542 LY_CHECK_RET(parse_ext(ctx, word, word_len, restr_kw, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001543 break;
1544 default:
David Sedlákb3077192019-06-19 10:55:37 +02001545 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001546 return LY_EVALID;
1547 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001548 }
Michal Vasko12ef5362022-09-16 15:13:58 +02001549
1550cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001551 return ret;
1552}
1553
Michal Vaskoea5abea2018-09-18 13:10:54 +02001554/**
1555 * @brief Parse a restriction that can have more instances such as must.
1556 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001557 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001558 * @param[in] restr_kw Type of this particular restriction.
1559 * @param[in,out] restrs Restrictions to add to.
1560 *
1561 * @return LY_ERR values.
1562 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001563static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001564parse_restrs(struct lys_yang_parser_ctx *ctx, enum ly_stmt restr_kw, struct lysp_restr **restrs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001565{
1566 struct lysp_restr *restr;
1567
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001568 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Radek Krejci33090f92020-12-17 20:12:46 +01001569 return parse_restr(ctx, restr_kw, restr);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001570}
1571
Michal Vaskoea5abea2018-09-18 13:10:54 +02001572/**
1573 * @brief Parse the status statement.
1574 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001575 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001576 * @param[in,out] flags Flags to add to.
1577 * @param[in,out] exts Extension instances to add to.
1578 *
1579 * @return LY_ERR values.
1580 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001581static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001582parse_status(struct lys_yang_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001583{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001584 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001585 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001586 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001587 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001588
1589 if (*flags & LYS_STATUS_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001590 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001591 return LY_EVALID;
1592 }
1593
1594 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001595 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001596
Radek Krejcif13b87b2020-12-01 22:02:17 +01001597 if ((word_len == ly_strlen_const("current")) && !strncmp(word, "current", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001598 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001599 } else if ((word_len == ly_strlen_const("deprecated")) && !strncmp(word, "deprecated", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001600 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001601 } else if ((word_len == ly_strlen_const("obsolete")) && !strncmp(word, "obsolete", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001602 *flags |= LYS_STATUS_OBSLT;
1603 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001604 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001605 free(buf);
1606 return LY_EVALID;
1607 }
1608 free(buf);
1609
aPieceka24a2252021-05-07 10:52:31 +02001610 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001611 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001612 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001613 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001614 break;
1615 default:
David Sedlákb3077192019-06-19 10:55:37 +02001616 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001617 return LY_EVALID;
1618 }
1619 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001620 return ret;
1621}
1622
Michal Vaskoea5abea2018-09-18 13:10:54 +02001623/**
1624 * @brief Parse the when statement.
1625 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001626 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001627 * @param[in,out] when_p When pointer to parse to.
1628 *
1629 * @return LY_ERR values.
1630 */
Radek Krejcif09e4e82019-06-14 15:08:11 +02001631LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001632parse_when(struct lys_yang_parser_ctx *ctx, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001633{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001634 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001635 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001636 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001637 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001638 struct lysp_when *when;
Michal Vaskoc636ea42022-09-16 10:20:31 +02001639 struct lysf_ctx fctx = {.ctx = PARSER_CTX(ctx)};
Michal Vasko7fbc8162018-09-17 10:35:16 +02001640
1641 if (*when_p) {
David Sedlákb3077192019-06-19 10:55:37 +02001642 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001643 return LY_EVALID;
1644 }
1645
1646 when = calloc(1, sizeof *when);
Michal Vasko12ef5362022-09-16 15:13:58 +02001647 LY_CHECK_ERR_GOTO(!when, LOGMEM(PARSER_CTX(ctx)); ret = LY_EMEM, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001648
1649 /* get value */
Michal Vasko12ef5362022-09-16 15:13:58 +02001650 LY_CHECK_GOTO(ret = get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len), cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01001651 CHECK_NONEMPTY(ctx, word_len, "when");
Michal Vasko12ef5362022-09-16 15:13:58 +02001652 INSERT_WORD_GOTO(ctx, buf, when->cond, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001653
Michal Vasko12ef5362022-09-16 15:13:58 +02001654 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto cleanup, goto cleanup) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001655 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001656 case LY_STMT_DESCRIPTION:
Michal Vasko12ef5362022-09-16 15:13:58 +02001657 LY_CHECK_GOTO(ret = parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001658 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001659 case LY_STMT_REFERENCE:
Michal Vasko12ef5362022-09-16 15:13:58 +02001660 LY_CHECK_GOTO(ret = parse_text_field(ctx, LY_STMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001661 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001662 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko12ef5362022-09-16 15:13:58 +02001663 LY_CHECK_GOTO(ret = parse_ext(ctx, word, word_len, LY_STMT_WHEN, 0, &when->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001664 break;
1665 default:
David Sedlákb3077192019-06-19 10:55:37 +02001666 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko12ef5362022-09-16 15:13:58 +02001667 ret = LY_EVALID;
1668 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001669 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001670 }
Michal Vasko12ef5362022-09-16 15:13:58 +02001671
1672cleanup:
1673 if (ret) {
Michal Vaskoc636ea42022-09-16 10:20:31 +02001674 lysp_when_free(&fctx, when);
Michal Vasko12ef5362022-09-16 15:13:58 +02001675 free(when);
1676 } else {
1677 *when_p = when;
1678 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001679 return ret;
1680}
1681
Michal Vaskoea5abea2018-09-18 13:10:54 +02001682/**
1683 * @brief Parse the anydata or anyxml statement.
1684 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001685 * @param[in] ctx yang parser context for logging.
Radek Krejci39b7fc22021-02-26 23:29:18 +01001686 * @param[in] any_kw Type of this particular keyword.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001687 * @param[in,out] siblings Siblings to add to.
1688 *
1689 * @return LY_ERR values.
1690 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02001691LY_ERR
Radek Krejci39b7fc22021-02-26 23:29:18 +01001692parse_any(struct lys_yang_parser_ctx *ctx, enum ly_stmt any_kw, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001693{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001694 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001695 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001696 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001697 struct lysp_node_anydata *any;
Radek Krejci39b7fc22021-02-26 23:29:18 +01001698 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001699
David Sedlák60adc092019-08-06 15:57:02 +02001700 /* create new structure and insert into siblings */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001701 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
David Sedlák60adc092019-08-06 15:57:02 +02001702
Radek Krejci39b7fc22021-02-26 23:29:18 +01001703 any->nodetype = any_kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001704 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001705
Michal Vasko7fbc8162018-09-17 10:35:16 +02001706 /* get name */
Radek Krejci33090f92020-12-17 20:12:46 +01001707 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02001708 INSERT_WORD_GOTO(ctx, buf, any->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001709
1710 /* parse substatements */
aPieceka24a2252021-05-07 10:52:31 +02001711 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001712 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001713 case LY_STMT_CONFIG:
Radek Krejci33090f92020-12-17 20:12:46 +01001714 LY_CHECK_RET(parse_config(ctx, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001715 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001716 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01001717 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001718 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001719 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001720 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &any->iffeatures, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001721 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001722 case LY_STMT_MANDATORY:
Radek Krejci33090f92020-12-17 20:12:46 +01001723 LY_CHECK_RET(parse_mandatory(ctx, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001724 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001725 case LY_STMT_MUST:
Radek Krejci33090f92020-12-17 20:12:46 +01001726 LY_CHECK_RET(parse_restrs(ctx, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001727 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001728 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001729 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001730 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001731 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01001732 LY_CHECK_RET(parse_status(ctx, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001733 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001734 case LY_STMT_WHEN:
Radek Krejci33090f92020-12-17 20:12:46 +01001735 LY_CHECK_RET(parse_when(ctx, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001736 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001737 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001738 LY_CHECK_RET(parse_ext(ctx, word, word_len, any_kw, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001739 break;
1740 default:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001741 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(any_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001742 return LY_EVALID;
1743 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001744 }
Michal Vasko12ef5362022-09-16 15:13:58 +02001745
1746cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001747 return ret;
1748}
1749
Michal Vaskoea5abea2018-09-18 13:10:54 +02001750/**
1751 * @brief Parse the value or position statement. Substatement of type enum statement.
1752 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001753 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001754 * @param[in] val_kw Type of this particular keyword.
1755 * @param[in,out] value Value to write to.
1756 * @param[in,out] flags Flags to write to.
1757 * @param[in,out] exts Extension instances to add to.
1758 *
1759 * @return LY_ERR values.
1760 */
David Sedlákd6ce6d72019-07-16 17:30:18 +02001761LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001762parse_type_enum_value_pos(struct lys_yang_parser_ctx *ctx, enum ly_stmt val_kw, int64_t *value, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +02001763 struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001764{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001765 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001766 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001767 size_t word_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001768 long long int num = 0;
1769 unsigned long long int unum = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001770 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001771
1772 if (*flags & LYS_SET_VALUE) {
David Sedlákb3077192019-06-19 10:55:37 +02001773 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001774 return LY_EVALID;
1775 }
1776 *flags |= LYS_SET_VALUE;
1777
1778 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001779 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001780
Radek Krejcid6b76452019-09-03 17:03:03 +02001781 if (!word_len || (word[0] == '+') || ((word[0] == '0') && (word_len > 1)) || ((val_kw == LY_STMT_POSITION) && !strncmp(word, "-0", 2))) {
David Sedlákb3077192019-06-19 10:55:37 +02001782 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001783 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001784 }
1785
1786 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001787 if (val_kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001788 num = strtoll(word, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001789 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
David Sedlákb3077192019-06-19 10:55:37 +02001790 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001791 goto error;
1792 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001793 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001794 unum = strtoull(word, &ptr, LY_BASE_DEC);
Radek Krejci8b764662018-11-14 14:15:13 +01001795 if (unum > UINT64_C(4294967295)) {
David Sedlákb3077192019-06-19 10:55:37 +02001796 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001797 goto error;
1798 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001799 }
1800 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001801 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001802 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001803 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001804 }
1805 if (errno == ERANGE) {
David Sedlákb3077192019-06-19 10:55:37 +02001806 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001807 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001808 }
Radek Krejcid6b76452019-09-03 17:03:03 +02001809 if (val_kw == LY_STMT_VALUE) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001810 *value = num;
1811 } else {
1812 *value = unum;
1813 }
1814 free(buf);
1815
aPieceka24a2252021-05-07 10:52:31 +02001816 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001817 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001818 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001819 LY_CHECK_RET(parse_ext(ctx, word, word_len, val_kw == LY_STMT_VALUE ? LY_STMT_VALUE : LY_STMT_POSITION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001820 break;
1821 default:
David Sedlákb3077192019-06-19 10:55:37 +02001822 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001823 return LY_EVALID;
1824 }
1825 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001826 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001827
1828error:
1829 free(buf);
1830 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001831}
1832
Michal Vaskoea5abea2018-09-18 13:10:54 +02001833/**
1834 * @brief Parse the enum or bit statement. Substatement of type statement.
1835 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001836 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001837 * @param[in] enum_kw Type of this particular keyword.
1838 * @param[in,out] enums Enums or bits to add to.
1839 *
1840 * @return LY_ERR values.
1841 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001842static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001843parse_type_enum(struct lys_yang_parser_ctx *ctx, enum ly_stmt enum_kw, struct lysp_type_enum **enums)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001844{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001845 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001846 char *buf, *word;
David Sedlák6544c182019-07-12 13:17:33 +02001847 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001848 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001849 struct lysp_type_enum *enm;
1850
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001851 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001852
1853 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001854 LY_CHECK_RET(get_argument(ctx, enum_kw == LY_STMT_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejcid6b76452019-09-03 17:03:03 +02001855 if (enum_kw == LY_STMT_ENUM) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001856 ret = lysp_check_enum_name((struct lys_parser_ctx *)ctx, (const char *)word, word_len);
David Sedlák6544c182019-07-12 13:17:33 +02001857 LY_CHECK_ERR_RET(ret, free(buf), ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001858 } /* else nothing specific for YANG_BIT */
Radek Krejci8b764662018-11-14 14:15:13 +01001859
Michal Vasko12ef5362022-09-16 15:13:58 +02001860 INSERT_WORD_GOTO(ctx, buf, enm->name, word, word_len, ret, cleanup);
Radek Krejci8b764662018-11-14 14:15:13 +01001861 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1862
aPieceka24a2252021-05-07 10:52:31 +02001863 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001864 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001865 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01001866 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001867 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001868 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02001869 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejcifc596f92021-02-26 22:40:26 +01001870 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001871 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001872 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001873 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001874 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001875 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01001876 LY_CHECK_RET(parse_status(ctx, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001877 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001878 case LY_STMT_VALUE:
1879 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 +02001880 ly_stmt2str(enum_kw)), LY_EVALID);
Radek Krejci33090f92020-12-17 20:12:46 +01001881 LY_CHECK_RET(parse_type_enum_value_pos(ctx, kw, &enm->value, &enm->flags, &enm->exts));
David Sedlák9fb515f2019-07-11 10:33:58 +02001882 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001883 case LY_STMT_POSITION:
1884 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 +02001885 ly_stmt2str(enum_kw)), LY_EVALID);
Radek Krejci33090f92020-12-17 20:12:46 +01001886 LY_CHECK_RET(parse_type_enum_value_pos(ctx, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001887 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001888 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01001889 LY_CHECK_RET(parse_ext(ctx, word, word_len, enum_kw, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001890 break;
1891 default:
David Sedlákb3077192019-06-19 10:55:37 +02001892 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001893 return LY_EVALID;
1894 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001895 }
Michal Vasko12ef5362022-09-16 15:13:58 +02001896
1897cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001898 return ret;
1899}
1900
Michal Vaskoea5abea2018-09-18 13:10:54 +02001901/**
1902 * @brief Parse the fraction-digits statement. Substatement of type statement.
1903 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001904 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001905 * @param[in,out] fracdig Value to write to.
1906 * @param[in,out] exts Extension instances to add to.
1907 *
1908 * @return LY_ERR values.
1909 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001910static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001911parse_type_fracdigits(struct lys_yang_parser_ctx *ctx, uint8_t *fracdig, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001912{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001913 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001914 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001915 size_t word_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001916 unsigned long long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02001917 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001918
1919 if (*fracdig) {
David Sedlákb3077192019-06-19 10:55:37 +02001920 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001921 return LY_EVALID;
1922 }
1923
1924 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001925 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001926
1927 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
David Sedlákb3077192019-06-19 10:55:37 +02001928 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001929 free(buf);
1930 return LY_EVALID;
1931 }
1932
1933 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001934 num = strtoull(word, &ptr, LY_BASE_DEC);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001935 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001936 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001937 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001938 free(buf);
1939 return LY_EVALID;
1940 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001941 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02001942 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001943 free(buf);
1944 return LY_EVALID;
1945 }
1946 *fracdig = num;
1947 free(buf);
1948
aPieceka24a2252021-05-07 10:52:31 +02001949 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001950 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001951 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01001952 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_FRACTION_DIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001953 break;
1954 default:
David Sedlákb3077192019-06-19 10:55:37 +02001955 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001956 return LY_EVALID;
1957 }
1958 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001959 return ret;
1960}
1961
Michal Vaskoea5abea2018-09-18 13:10:54 +02001962/**
1963 * @brief Parse the require-instance statement. Substatement of type statement.
1964 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001965 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001966 * @param[in,out] reqinst Value to write to.
1967 * @param[in,out] flags Flags to write to.
1968 * @param[in,out] exts Extension instances to add to.
1969 *
1970 * @return LY_ERR values.
1971 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001972static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01001973parse_type_reqinstance(struct lys_yang_parser_ctx *ctx, uint8_t *reqinst, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +02001974 struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001975{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001976 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001977 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001978 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001979 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001980
1981 if (*flags & LYS_SET_REQINST) {
David Sedlákb3077192019-06-19 10:55:37 +02001982 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001983 return LY_EVALID;
1984 }
1985 *flags |= LYS_SET_REQINST;
1986
1987 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01001988 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001989
Radek Krejcif13b87b2020-12-01 22:02:17 +01001990 if ((word_len == ly_strlen_const("true")) && !strncmp(word, "true", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001991 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001992 } else if ((word_len != ly_strlen_const("false")) || strncmp(word, "false", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02001993 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001994 free(buf);
1995 return LY_EVALID;
1996 }
1997 free(buf);
1998
aPieceka24a2252021-05-07 10:52:31 +02001999 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002000 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002001 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002002 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_REQUIRE_INSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002003 break;
2004 default:
David Sedlákb3077192019-06-19 10:55:37 +02002005 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002006 return LY_EVALID;
2007 }
2008 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002009 return ret;
2010}
2011
Michal Vaskoea5abea2018-09-18 13:10:54 +02002012/**
2013 * @brief Parse the modifier statement. Substatement of type pattern statement.
2014 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002015 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002016 * @param[in,out] pat Value to write to.
2017 * @param[in,out] exts Extension instances to add to.
2018 *
2019 * @return LY_ERR values.
2020 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002021static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01002022parse_type_pattern_modifier(struct lys_yang_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002023{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002024 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002025 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002026 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002027 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002028
Radek Krejcif13b87b2020-12-01 22:02:17 +01002029 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
David Sedlákb3077192019-06-19 10:55:37 +02002030 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002031 return LY_EVALID;
2032 }
2033
2034 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01002035 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002036
Radek Krejcif13b87b2020-12-01 22:02:17 +01002037 if ((word_len != ly_strlen_const("invert-match")) || strncmp(word, "invert-match", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02002038 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002039 free(buf);
2040 return LY_EVALID;
2041 }
2042 free(buf);
2043
2044 /* replace the value in the dictionary */
2045 buf = malloc(strlen(*pat) + 1);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002046 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002047 strcpy(buf, *pat);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002048 lydict_remove(PARSER_CTX(ctx), *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002049
Radek Krejcif13b87b2020-12-01 22:02:17 +01002050 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
2051 buf[0] = LYSP_RESTR_PATTERN_NACK;
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002052 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002053
aPieceka24a2252021-05-07 10:52:31 +02002054 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002055 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002056 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002057 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002058 break;
2059 default:
David Sedlákb3077192019-06-19 10:55:37 +02002060 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002061 return LY_EVALID;
2062 }
2063 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002064 return ret;
2065}
2066
Michal Vaskoea5abea2018-09-18 13:10:54 +02002067/**
2068 * @brief Parse the pattern statement. Substatement of type statement.
2069 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002070 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002071 * @param[in,out] patterns Restrictions to add to.
2072 *
2073 * @return LY_ERR values.
2074 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002075static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01002076parse_type_pattern(struct lys_yang_parser_ctx *ctx, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002077{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002078 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002079 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002080 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002081 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002082 struct lysp_restr *restr;
2083
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002084 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002085
2086 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01002087 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002088
2089 /* add special meaning first byte */
2090 if (buf) {
Radek Krejcif13b87b2020-12-01 22:02:17 +01002091 buf = ly_realloc(buf, word_len + 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002092 word = buf;
2093 } else {
2094 buf = malloc(word_len + 2);
2095 }
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002096 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko54720192021-06-11 13:55:59 +02002097 if (word_len) {
2098 memmove(buf + 1, word, word_len);
2099 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01002100 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci86d106e2018-10-18 09:53:19 +02002101 buf[word_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002102 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +01002103 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002104
aPieceka24a2252021-05-07 10:52:31 +02002105 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002106 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002107 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01002108 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002109 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002110 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002111 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002112 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002113 case LY_STMT_ERROR_APP_TAG:
Radek Krejcifc596f92021-02-26 22:40:26 +01002114 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_ERROR_APP_TAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002115 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002116 case LY_STMT_ERROR_MESSAGE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002117 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_ERROR_MESSAGE, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002118 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002119 case LY_STMT_MODIFIER:
Radek Krejci335332a2019-09-05 13:03:35 +02002120 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci33090f92020-12-17 20:12:46 +01002121 LY_CHECK_RET(parse_type_pattern_modifier(ctx, &restr->arg.str, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002122 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002123 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002124 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_PATTERN, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002125 break;
2126 default:
David Sedlákb3077192019-06-19 10:55:37 +02002127 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002128 return LY_EVALID;
2129 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002130 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002131 return ret;
2132}
2133
Michal Vaskoea5abea2018-09-18 13:10:54 +02002134/**
2135 * @brief Parse the type statement.
2136 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002137 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002138 * @param[in,out] type Type to wrote to.
2139 *
2140 * @return LY_ERR values.
2141 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002142static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01002143parse_type(struct lys_yang_parser_ctx *ctx, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002144{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002145 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002146 char *buf, *word;
Michal Vasko004d3152020-06-11 19:59:22 +02002147 const char *str_path = NULL;
Radek Krejciefd22f62018-09-27 11:47:58 +02002148 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002149 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002150 struct lysp_type *nest_type;
2151
2152 if (type->name) {
David Sedlákb3077192019-06-19 10:55:37 +02002153 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002154 return LY_EVALID;
2155 }
2156
2157 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01002158 LY_CHECK_RET(get_argument(ctx, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02002159 INSERT_WORD_GOTO(ctx, buf, type->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002160
Michal Vaskoe9c050f2020-10-06 14:01:23 +02002161 /* set module */
Michal Vasko8a67eff2021-12-07 14:04:47 +01002162 type->pmod = PARSER_CUR_PMOD(ctx);
Michal Vaskoe9c050f2020-10-06 14:01:23 +02002163
aPieceka24a2252021-05-07 10:52:31 +02002164 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002165 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002166 case LY_STMT_BASE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002167 LY_CHECK_RET(parse_text_fields(ctx, LY_STMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002168 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002169 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002170 case LY_STMT_BIT:
Radek Krejci33090f92020-12-17 20:12:46 +01002171 LY_CHECK_RET(parse_type_enum(ctx, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002172 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002173 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002174 case LY_STMT_ENUM:
Radek Krejci33090f92020-12-17 20:12:46 +01002175 LY_CHECK_RET(parse_type_enum(ctx, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002176 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002177 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002178 case LY_STMT_FRACTION_DIGITS:
Radek Krejci33090f92020-12-17 20:12:46 +01002179 LY_CHECK_RET(parse_type_fracdigits(ctx, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002180 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002181 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002182 case LY_STMT_LENGTH:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002183 if (type->length) {
David Sedlákb3077192019-06-19 10:55:37 +02002184 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002185 return LY_EVALID;
2186 }
2187 type->length = calloc(1, sizeof *type->length);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002188 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189
Radek Krejci33090f92020-12-17 20:12:46 +01002190 LY_CHECK_RET(parse_restr(ctx, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002191 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002192 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002193 case LY_STMT_PATH:
Michal Vasko004d3152020-06-11 19:59:22 +02002194 if (type->path) {
Radek Krejci3972b332021-03-02 16:34:31 +01002195 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(LY_STMT_PATH));
Michal Vasko004d3152020-06-11 19:59:22 +02002196 return LY_EVALID;
2197 }
2198
aPiecek4bb1e372021-05-07 11:01:00 +02002199 /* Usually, in the parser_yang.c, the result of the parsing is stored directly in the
2200 * corresponding structure, so in case of failure, the lysp_module_free function will take
2201 * care of removing the parsed value from the dictionary. But in this case, it is not possible
2202 * to rely on lysp_module_free because the result of the parsing is stored in a local variable.
2203 */
2204 LY_CHECK_ERR_RET(ret = parse_text_field(ctx, LY_STMT_PATH, 0, &str_path, Y_STR_ARG, &type->exts),
2205 lydict_remove(PARSER_CTX(ctx), str_path), ret);
Michal Vaskoed725d72021-06-23 12:03:45 +02002206 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +02002207 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
aPiecek4bb1e372021-05-07 11:01:00 +02002208 /* Moreover, even if successful, the string is removed from the dictionary. */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002209 lydict_remove(PARSER_CTX(ctx), str_path);
Michal Vasko004d3152020-06-11 19:59:22 +02002210 LY_CHECK_RET(ret);
Radek Krejcid505e3d2018-11-13 09:04:17 +01002211 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002212 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002213 case LY_STMT_PATTERN:
Radek Krejci33090f92020-12-17 20:12:46 +01002214 LY_CHECK_RET(parse_type_pattern(ctx, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002215 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002216 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002217 case LY_STMT_RANGE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002218 if (type->range) {
David Sedlákb3077192019-06-19 10:55:37 +02002219 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002220 return LY_EVALID;
2221 }
2222 type->range = calloc(1, sizeof *type->range);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002223 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002224
Radek Krejci33090f92020-12-17 20:12:46 +01002225 LY_CHECK_RET(parse_restr(ctx, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002226 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002227 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002228 case LY_STMT_REQUIRE_INSTANCE:
Radek Krejci33090f92020-12-17 20:12:46 +01002229 LY_CHECK_RET(parse_type_reqinstance(ctx, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002230 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002231 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002232 case LY_STMT_TYPE:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002233 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Radek Krejci33090f92020-12-17 20:12:46 +01002234 LY_CHECK_RET(parse_type(ctx, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002235 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002236 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002237 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002238 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_TYPE, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002239 break;
2240 default:
David Sedlákb3077192019-06-19 10:55:37 +02002241 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002242 return LY_EVALID;
2243 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002244 }
Michal Vasko12ef5362022-09-16 15:13:58 +02002245
2246cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002247 return ret;
2248}
2249
Michal Vaskoea5abea2018-09-18 13:10:54 +02002250/**
2251 * @brief Parse the leaf statement.
2252 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002253 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002254 * @param[in,out] siblings Siblings to add to.
2255 *
2256 * @return LY_ERR values.
2257 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002258LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01002259parse_leaf(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002260{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002261 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002262 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002263 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002264 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002265 struct lysp_node_leaf *leaf;
2266
David Sedlák60adc092019-08-06 15:57:02 +02002267 /* create new leaf structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002268 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002269 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002270 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002271
Michal Vasko7fbc8162018-09-17 10:35:16 +02002272 /* get name */
Radek Krejci33090f92020-12-17 20:12:46 +01002273 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02002274 INSERT_WORD_GOTO(ctx, buf, leaf->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002275
2276 /* parse substatements */
aPieceka24a2252021-05-07 10:52:31 +02002277 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002278 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002279 case LY_STMT_CONFIG:
Radek Krejci33090f92020-12-17 20:12:46 +01002280 LY_CHECK_RET(parse_config(ctx, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002281 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002282 case LY_STMT_DEFAULT:
Radek Krejcifc596f92021-02-26 22:40:26 +01002283 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DEFAULT, 0, &leaf->dflt.str, Y_STR_ARG, &leaf->exts));
Michal Vasko8a67eff2021-12-07 14:04:47 +01002284 leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002285 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002286 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01002287 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002288 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002289 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002290 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002291 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002292 case LY_STMT_MANDATORY:
Radek Krejci33090f92020-12-17 20:12:46 +01002293 LY_CHECK_RET(parse_mandatory(ctx, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002294 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002295 case LY_STMT_MUST:
Radek Krejci33090f92020-12-17 20:12:46 +01002296 LY_CHECK_RET(parse_restrs(ctx, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002297 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002298 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002299 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002300 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002301 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01002302 LY_CHECK_RET(parse_status(ctx, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002303 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002304 case LY_STMT_TYPE:
Radek Krejci33090f92020-12-17 20:12:46 +01002305 LY_CHECK_RET(parse_type(ctx, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002306 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002307 case LY_STMT_UNITS:
Radek Krejcifc596f92021-02-26 22:40:26 +01002308 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002309 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002310 case LY_STMT_WHEN:
Radek Krejci33090f92020-12-17 20:12:46 +01002311 LY_CHECK_RET(parse_when(ctx, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002312 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002313 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002314 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_LEAF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002315 break;
2316 default:
David Sedlákb3077192019-06-19 10:55:37 +02002317 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002318 return LY_EVALID;
2319 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002320 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002321 LY_CHECK_RET(ret);
Michal Vasko12ef5362022-09-16 15:13:58 +02002322
Radek Krejci6d6556c2018-11-08 09:37:45 +01002323checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002324 /* mandatory substatements */
2325 if (!leaf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002326 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002327 return LY_EVALID;
2328 }
2329
Michal Vasko12ef5362022-09-16 15:13:58 +02002330cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002331 return ret;
2332}
2333
Michal Vaskoea5abea2018-09-18 13:10:54 +02002334/**
2335 * @brief Parse the max-elements statement.
2336 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002337 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002338 * @param[in,out] max Value to write to.
2339 * @param[in,out] flags Flags to write to.
2340 * @param[in,out] exts Extension instances to add to.
2341 *
2342 * @return LY_ERR values.
2343 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002344LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01002345parse_maxelements(struct lys_yang_parser_ctx *ctx, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002346{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002347 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002348 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002349 size_t word_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002350 unsigned long long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02002351 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002352
2353 if (*flags & LYS_SET_MAX) {
David Sedlákb3077192019-06-19 10:55:37 +02002354 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002355 return LY_EVALID;
2356 }
2357 *flags |= LYS_SET_MAX;
2358
2359 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01002360 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002361
2362 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
David Sedlákb3077192019-06-19 10:55:37 +02002363 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002364 free(buf);
2365 return LY_EVALID;
2366 }
2367
Radek Krejci7f9b6512019-09-18 13:11:09 +02002368 if (ly_strncmp("unbounded", word, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002369 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002370 num = strtoull(word, &ptr, LY_BASE_DEC);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002371 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002372 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002373 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002374 free(buf);
2375 return LY_EVALID;
2376 }
2377 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002378 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002379 free(buf);
2380 return LY_EVALID;
2381 }
2382
2383 *max = num;
Radek Krejcid6315102021-02-02 15:26:34 +01002384 } else {
2385 /* unbounded */
2386 *max = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002387 }
2388 free(buf);
2389
aPieceka24a2252021-05-07 10:52:31 +02002390 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002391 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002392 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002393 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_MAX_ELEMENTS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002394 break;
2395 default:
David Sedlákb3077192019-06-19 10:55:37 +02002396 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002397 return LY_EVALID;
2398 }
2399 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002400 return ret;
2401}
2402
Michal Vaskoea5abea2018-09-18 13:10:54 +02002403/**
2404 * @brief Parse the min-elements statement.
2405 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002406 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002407 * @param[in,out] min Value to write to.
2408 * @param[in,out] flags Flags to write to.
2409 * @param[in,out] exts Extension instances to add to.
2410 *
2411 * @return LY_ERR values.
2412 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002413LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01002414parse_minelements(struct lys_yang_parser_ctx *ctx, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002415{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002416 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002417 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002418 size_t word_len;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002419 unsigned long long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02002420 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002421
2422 if (*flags & LYS_SET_MIN) {
David Sedlákb3077192019-06-19 10:55:37 +02002423 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002424 return LY_EVALID;
2425 }
2426 *flags |= LYS_SET_MIN;
2427
2428 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01002429 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002430
2431 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
David Sedlákb3077192019-06-19 10:55:37 +02002432 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002433 free(buf);
2434 return LY_EVALID;
2435 }
2436
2437 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02002438 num = strtoull(word, &ptr, LY_BASE_DEC);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002439 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002440 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002441 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002442 free(buf);
2443 return LY_EVALID;
2444 }
2445 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002446 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002447 free(buf);
2448 return LY_EVALID;
2449 }
2450 *min = num;
2451 free(buf);
2452
aPieceka24a2252021-05-07 10:52:31 +02002453 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002454 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002455 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002456 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_MIN_ELEMENTS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002457 break;
2458 default:
David Sedlákb3077192019-06-19 10:55:37 +02002459 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002460 return LY_EVALID;
2461 }
2462 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002463 return ret;
2464}
2465
Michal Vaskoea5abea2018-09-18 13:10:54 +02002466/**
2467 * @brief Parse the ordered-by statement.
2468 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002469 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002470 * @param[in,out] flags Flags to write to.
2471 * @param[in,out] exts Extension instances to add to.
2472 *
2473 * @return LY_ERR values.
2474 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002475static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01002476parse_orderedby(struct lys_yang_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002477{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002478 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002479 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002480 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002481 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002482
2483 if (*flags & LYS_ORDBY_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02002484 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002485 return LY_EVALID;
2486 }
2487
2488 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01002489 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002490
Radek Krejcif13b87b2020-12-01 22:02:17 +01002491 if ((word_len == ly_strlen_const("system")) && !strncmp(word, "system", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002492 *flags |= LYS_ORDBY_SYSTEM;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002493 } else if ((word_len == ly_strlen_const("user")) && !strncmp(word, "user", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002494 *flags |= LYS_ORDBY_USER;
2495 } else {
David Sedlákb3077192019-06-19 10:55:37 +02002496 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002497 free(buf);
2498 return LY_EVALID;
2499 }
2500 free(buf);
2501
aPieceka24a2252021-05-07 10:52:31 +02002502 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002503 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002504 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002505 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_ORDERED_BY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002506 break;
2507 default:
David Sedlákb3077192019-06-19 10:55:37 +02002508 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002509 return LY_EVALID;
2510 }
2511 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002512 return ret;
2513}
2514
Michal Vaskoea5abea2018-09-18 13:10:54 +02002515/**
2516 * @brief Parse the leaf-list statement.
2517 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002518 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002519 * @param[in,out] siblings Siblings to add to.
2520 *
2521 * @return LY_ERR values.
2522 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002523LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01002524parse_leaflist(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002525{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002526 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002527 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002528 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002529 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002530 struct lysp_node_leaflist *llist;
2531
David Sedlák60adc092019-08-06 15:57:02 +02002532 /* create new leaf-list structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002533 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002534 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002535 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002536
Michal Vasko7fbc8162018-09-17 10:35:16 +02002537 /* get name */
Radek Krejci33090f92020-12-17 20:12:46 +01002538 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02002539 INSERT_WORD_GOTO(ctx, buf, llist->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002540
2541 /* parse substatements */
aPieceka24a2252021-05-07 10:52:31 +02002542 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002543 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002544 case LY_STMT_CONFIG:
Radek Krejci33090f92020-12-17 20:12:46 +01002545 LY_CHECK_RET(parse_config(ctx, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002546 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002547 case LY_STMT_DEFAULT:
Radek Krejci335332a2019-09-05 13:03:35 +02002548 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejcifc596f92021-02-26 22:40:26 +01002549 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002550 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002551 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01002552 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002553 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002554 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002555 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002556 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002557 case LY_STMT_MAX_ELEMENTS:
Radek Krejci33090f92020-12-17 20:12:46 +01002558 LY_CHECK_RET(parse_maxelements(ctx, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002559 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002560 case LY_STMT_MIN_ELEMENTS:
Radek Krejci33090f92020-12-17 20:12:46 +01002561 LY_CHECK_RET(parse_minelements(ctx, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002562 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002563 case LY_STMT_MUST:
Radek Krejci33090f92020-12-17 20:12:46 +01002564 LY_CHECK_RET(parse_restrs(ctx, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002565 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002566 case LY_STMT_ORDERED_BY:
Radek Krejci33090f92020-12-17 20:12:46 +01002567 LY_CHECK_RET(parse_orderedby(ctx, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002568 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002569 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002570 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002571 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002572 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01002573 LY_CHECK_RET(parse_status(ctx, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002574 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002575 case LY_STMT_TYPE:
Radek Krejci33090f92020-12-17 20:12:46 +01002576 LY_CHECK_RET(parse_type(ctx, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002577 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002578 case LY_STMT_UNITS:
Radek Krejcifc596f92021-02-26 22:40:26 +01002579 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002580 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002581 case LY_STMT_WHEN:
Radek Krejci33090f92020-12-17 20:12:46 +01002582 LY_CHECK_RET(parse_when(ctx, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002583 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002584 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002585 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_LEAF_LIST, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002586 break;
2587 default:
David Sedlákb3077192019-06-19 10:55:37 +02002588 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002589 return LY_EVALID;
2590 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002591 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002592 LY_CHECK_RET(ret);
Michal Vasko12ef5362022-09-16 15:13:58 +02002593
Radek Krejci6d6556c2018-11-08 09:37:45 +01002594checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002595 /* mandatory substatements */
2596 if (!llist->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002597 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002598 return LY_EVALID;
2599 }
2600
Michal Vasko12ef5362022-09-16 15:13:58 +02002601cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002602 return ret;
2603}
2604
Michal Vaskoea5abea2018-09-18 13:10:54 +02002605/**
2606 * @brief Parse the refine statement.
2607 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002608 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002609 * @param[in,out] refines Refines to add to.
2610 *
2611 * @return LY_ERR values.
2612 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002613static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01002614parse_refine(struct lys_yang_parser_ctx *ctx, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002615{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002616 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002617 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002618 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002619 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002620 struct lysp_refine *rf;
2621
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002622 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002623
2624 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01002625 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vaskob36053d2020-03-26 15:49:30 +01002626 CHECK_NONEMPTY(ctx, word_len, "refine");
Michal Vasko12ef5362022-09-16 15:13:58 +02002627 INSERT_WORD_GOTO(ctx, buf, rf->nodeid, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002628
aPieceka24a2252021-05-07 10:52:31 +02002629 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002630 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002631 case LY_STMT_CONFIG:
Radek Krejci33090f92020-12-17 20:12:46 +01002632 LY_CHECK_RET(parse_config(ctx, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002633 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002634 case LY_STMT_DEFAULT:
Radek Krejcifc596f92021-02-26 22:40:26 +01002635 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002636 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002637 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01002638 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002639 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002640 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02002641 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejcifc596f92021-02-26 22:40:26 +01002642 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002643 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002644 case LY_STMT_MAX_ELEMENTS:
Radek Krejci33090f92020-12-17 20:12:46 +01002645 LY_CHECK_RET(parse_maxelements(ctx, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002646 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002647 case LY_STMT_MIN_ELEMENTS:
Radek Krejci33090f92020-12-17 20:12:46 +01002648 LY_CHECK_RET(parse_minelements(ctx, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002649 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002650 case LY_STMT_MUST:
Radek Krejci33090f92020-12-17 20:12:46 +01002651 LY_CHECK_RET(parse_restrs(ctx, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002652 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002653 case LY_STMT_MANDATORY:
Radek Krejci33090f92020-12-17 20:12:46 +01002654 LY_CHECK_RET(parse_mandatory(ctx, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002655 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002656 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002657 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002658 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002659 case LY_STMT_PRESENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002660 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002661 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002662 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002663 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_REFINE, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002664 break;
2665 default:
David Sedlákb3077192019-06-19 10:55:37 +02002666 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002667 return LY_EVALID;
2668 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002669 }
Michal Vasko12ef5362022-09-16 15:13:58 +02002670
2671cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002672 return ret;
2673}
2674
Michal Vaskoea5abea2018-09-18 13:10:54 +02002675/**
2676 * @brief Parse the typedef statement.
2677 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002678 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002679 * @param[in,out] typedefs Typedefs to add to.
2680 *
2681 * @return LY_ERR values.
2682 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002683static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01002684parse_typedef(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002685{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002686 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002687 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002688 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002689 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002690 struct lysp_tpdf *tpdf;
2691
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002692 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002693
2694 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01002695 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02002696 INSERT_WORD_GOTO(ctx, buf, tpdf->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002697
2698 /* parse substatements */
aPieceka24a2252021-05-07 10:52:31 +02002699 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002700 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002701 case LY_STMT_DEFAULT:
Radek Krejcifc596f92021-02-26 22:40:26 +01002702 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DEFAULT, 0, &tpdf->dflt.str, Y_STR_ARG, &tpdf->exts));
Michal Vasko8a67eff2021-12-07 14:04:47 +01002703 tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002704 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002705 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01002706 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002707 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002708 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002709 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002710 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002711 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01002712 LY_CHECK_RET(parse_status(ctx, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002713 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002714 case LY_STMT_TYPE:
Radek Krejci33090f92020-12-17 20:12:46 +01002715 LY_CHECK_RET(parse_type(ctx, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002716 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002717 case LY_STMT_UNITS:
Radek Krejcifc596f92021-02-26 22:40:26 +01002718 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002719 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002720 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002721 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_TYPEDEF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002722 break;
2723 default:
David Sedlákb3077192019-06-19 10:55:37 +02002724 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002725 return LY_EVALID;
2726 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002727 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002728 LY_CHECK_RET(ret);
Michal Vasko12ef5362022-09-16 15:13:58 +02002729
Radek Krejcibbe09a92018-11-08 09:36:54 +01002730checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002731 /* mandatory substatements */
2732 if (!tpdf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002733 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002734 return LY_EVALID;
2735 }
2736
Radek Krejcibbe09a92018-11-08 09:36:54 +01002737 /* store data for collision check */
aPiecek75b83a02021-06-29 10:34:38 +02002738 if (parent) {
aPiecek8d4e75d2021-06-24 14:47:06 +02002739 assert(ctx->main_ctx);
2740 LY_CHECK_RET(ly_set_add(&ctx->main_ctx->tpdfs_nodes, parent, 0, NULL));
Radek Krejcibbe09a92018-11-08 09:36:54 +01002741 }
2742
Michal Vasko12ef5362022-09-16 15:13:58 +02002743cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002744 return ret;
2745}
2746
Michal Vaskoea5abea2018-09-18 13:10:54 +02002747/**
2748 * @brief Parse the input or output statement.
2749 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002750 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002751 * @param[in] kw Type of this particular keyword
2752 * @param[in,out] inout_p Input/output pointer to write to.
2753 *
2754 * @return LY_ERR values.
2755 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002756static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01002757parse_inout(struct lys_yang_parser_ctx *ctx, enum ly_stmt inout_kw, struct lysp_node *parent,
Radek Krejci2a9fc652021-01-22 17:44:34 +01002758 struct lysp_node_action_inout *inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002759{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002760 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002761 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002762 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002763 enum ly_stmt kw;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002764 ly_bool input = &((struct lysp_node_action *)parent)->input == inout_p ? 1 : 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002765
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002766 if (inout_p->nodetype) {
David Sedlákb3077192019-06-19 10:55:37 +02002767 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002768 return LY_EVALID;
2769 }
2770
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002771 /* initiate structure */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002772 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), input ? "input" : "output", 0, &inout_p->name));
2773 inout_p->nodetype = input ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002774 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002775
2776 /* parse substatements */
aPieceka24a2252021-05-07 10:52:31 +02002777 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002778 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002779 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002780 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci0f969882020-08-21 16:56:47 +02002781 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002782 case LY_STMT_ANYXML:
Radek Krejci01180ac2021-01-27 08:48:22 +01002783 LY_CHECK_RET(parse_any(ctx, kw, (struct lysp_node *)inout_p, &inout_p->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002784 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002785 case LY_STMT_CHOICE:
Radek Krejci01180ac2021-01-27 08:48:22 +01002786 LY_CHECK_RET(parse_choice(ctx, (struct lysp_node *)inout_p, &inout_p->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002787 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002788 case LY_STMT_CONTAINER:
Radek Krejci01180ac2021-01-27 08:48:22 +01002789 LY_CHECK_RET(parse_container(ctx, (struct lysp_node *)inout_p, &inout_p->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002791 case LY_STMT_LEAF:
Radek Krejci01180ac2021-01-27 08:48:22 +01002792 LY_CHECK_RET(parse_leaf(ctx, (struct lysp_node *)inout_p, &inout_p->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002793 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002794 case LY_STMT_LEAF_LIST:
Radek Krejci01180ac2021-01-27 08:48:22 +01002795 LY_CHECK_RET(parse_leaflist(ctx, (struct lysp_node *)inout_p, &inout_p->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002797 case LY_STMT_LIST:
Radek Krejci01180ac2021-01-27 08:48:22 +01002798 LY_CHECK_RET(parse_list(ctx, (struct lysp_node *)inout_p, &inout_p->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002799 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002800 case LY_STMT_USES:
Radek Krejci01180ac2021-01-27 08:48:22 +01002801 LY_CHECK_RET(parse_uses(ctx, (struct lysp_node *)inout_p, &inout_p->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002802 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002803 case LY_STMT_TYPEDEF:
Radek Krejci33090f92020-12-17 20:12:46 +01002804 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)inout_p, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002805 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002806 case LY_STMT_MUST:
Radek Krejci335332a2019-09-05 13:03:35 +02002807 PARSER_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci33090f92020-12-17 20:12:46 +01002808 LY_CHECK_RET(parse_restrs(ctx, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002809 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002810 case LY_STMT_GROUPING:
Radek Krejci33090f92020-12-17 20:12:46 +01002811 LY_CHECK_RET(parse_grouping(ctx, (struct lysp_node *)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002812 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002813 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002814 LY_CHECK_RET(parse_ext(ctx, word, word_len, inout_kw, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002815 break;
2816 default:
David Sedlákb3077192019-06-19 10:55:37 +02002817 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002818 return LY_EVALID;
2819 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002820 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002821 LY_CHECK_RET(ret);
Michal Vaskob83af8a2020-01-06 09:49:22 +01002822
Radek Krejci7fc68292019-06-12 13:51:09 +02002823checks:
Radek Krejci01180ac2021-01-27 08:48:22 +01002824 if (!inout_p->child) {
Michal Vaskob83af8a2020-01-06 09:49:22 +01002825 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2826 return LY_EVALID;
2827 }
2828
Michal Vasko7fbc8162018-09-17 10:35:16 +02002829 return ret;
2830}
2831
Michal Vaskoea5abea2018-09-18 13:10:54 +02002832/**
2833 * @brief Parse the action statement.
2834 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002835 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002836 * @param[in,out] actions Actions to add to.
2837 *
2838 * @return LY_ERR values.
2839 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002840LY_ERR
Radek Krejci2a9fc652021-01-22 17:44:34 +01002841parse_action(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002842{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002843 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002844 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002845 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002846 enum ly_stmt kw;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002847 struct lysp_node_action *act;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002848
Radek Krejci2a9fc652021-01-22 17:44:34 +01002849 LY_LIST_NEW_RET(PARSER_CTX(ctx), actions, act, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002850
2851 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01002852 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02002853 INSERT_WORD_GOTO(ctx, buf, act->name, word, word_len, ret, cleanup);
Michal Vasko1bf09392020-03-27 12:38:10 +01002854 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002855 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002856
aPieceka24a2252021-05-07 10:52:31 +02002857 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002858 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002859 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01002860 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002861 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002862 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002863 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &act->iffeatures, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002864 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002865 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002866 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002867 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002868 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01002869 LY_CHECK_RET(parse_status(ctx, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002870 break;
2871
Radek Krejcid6b76452019-09-03 17:03:03 +02002872 case LY_STMT_INPUT:
Radek Krejci33090f92020-12-17 20:12:46 +01002873 LY_CHECK_RET(parse_inout(ctx, kw, (struct lysp_node *)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002874 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002875 case LY_STMT_OUTPUT:
Radek Krejci33090f92020-12-17 20:12:46 +01002876 LY_CHECK_RET(parse_inout(ctx, kw, (struct lysp_node *)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002877 break;
2878
Radek Krejcid6b76452019-09-03 17:03:03 +02002879 case LY_STMT_TYPEDEF:
Radek Krejci33090f92020-12-17 20:12:46 +01002880 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)act, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002881 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002882 case LY_STMT_GROUPING:
Radek Krejci33090f92020-12-17 20:12:46 +01002883 LY_CHECK_RET(parse_grouping(ctx, (struct lysp_node *)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002884 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002885 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002886 LY_CHECK_RET(parse_ext(ctx, word, word_len, parent ? LY_STMT_ACTION : LY_STMT_RPC, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002887 break;
2888 default:
David Sedlákb3077192019-06-19 10:55:37 +02002889 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002890 return LY_EVALID;
2891 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002892 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002893 LY_CHECK_RET(ret);
Michal Vasko7f45cf22020-10-01 12:49:44 +02002894
Radek Krejci2a9fc652021-01-22 17:44:34 +01002895checks:
Michal Vasko7f45cf22020-10-01 12:49:44 +02002896 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2897 if (!act->input.nodetype) {
2898 act->input.nodetype = LYS_INPUT;
2899 act->input.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002900 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002901 }
2902 if (!act->output.nodetype) {
2903 act->output.nodetype = LYS_OUTPUT;
2904 act->output.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002905 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002906 }
2907
Michal Vasko12ef5362022-09-16 15:13:58 +02002908cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002909 return ret;
2910}
2911
Michal Vaskoea5abea2018-09-18 13:10:54 +02002912/**
2913 * @brief Parse the notification statement.
2914 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002915 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002916 * @param[in,out] notifs Notifications to add to.
2917 *
2918 * @return LY_ERR values.
2919 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002920LY_ERR
Radek Krejci2a9fc652021-01-22 17:44:34 +01002921parse_notif(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002922{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002923 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002924 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002925 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002926 enum ly_stmt kw;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002927 struct lysp_node_notif *notif;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002928
Radek Krejci2a9fc652021-01-22 17:44:34 +01002929 LY_LIST_NEW_RET(PARSER_CTX(ctx), notifs, notif, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002930
2931 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01002932 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02002933 INSERT_WORD_GOTO(ctx, buf, notif->name, word, word_len, ret, cleanup);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002934 notif->nodetype = LYS_NOTIF;
2935 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002936
aPieceka24a2252021-05-07 10:52:31 +02002937 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002938 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002939 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01002940 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002941 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002942 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002943 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002944 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002945 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01002946 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002947 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002948 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01002949 LY_CHECK_RET(parse_status(ctx, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002950 break;
2951
Radek Krejcid6b76452019-09-03 17:03:03 +02002952 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002953 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci0f969882020-08-21 16:56:47 +02002954 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002955 case LY_STMT_ANYXML:
Radek Krejci01180ac2021-01-27 08:48:22 +01002956 LY_CHECK_RET(parse_any(ctx, kw, (struct lysp_node *)notif, &notif->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002957 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002958 case LY_STMT_CHOICE:
Michal Vasko5ae1e1a2021-02-08 09:53:26 +01002959 LY_CHECK_RET(parse_choice(ctx, (struct lysp_node *)notif, &notif->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002960 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002961 case LY_STMT_CONTAINER:
Radek Krejci01180ac2021-01-27 08:48:22 +01002962 LY_CHECK_RET(parse_container(ctx, (struct lysp_node *)notif, &notif->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002963 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002964 case LY_STMT_LEAF:
Radek Krejci01180ac2021-01-27 08:48:22 +01002965 LY_CHECK_RET(parse_leaf(ctx, (struct lysp_node *)notif, &notif->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002966 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002967 case LY_STMT_LEAF_LIST:
Radek Krejci01180ac2021-01-27 08:48:22 +01002968 LY_CHECK_RET(parse_leaflist(ctx, (struct lysp_node *)notif, &notif->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002969 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002970 case LY_STMT_LIST:
Radek Krejci01180ac2021-01-27 08:48:22 +01002971 LY_CHECK_RET(parse_list(ctx, (struct lysp_node *)notif, &notif->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002972 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002973 case LY_STMT_USES:
Radek Krejci01180ac2021-01-27 08:48:22 +01002974 LY_CHECK_RET(parse_uses(ctx, (struct lysp_node *)notif, &notif->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002975 break;
2976
Radek Krejcid6b76452019-09-03 17:03:03 +02002977 case LY_STMT_MUST:
Radek Krejci335332a2019-09-05 13:03:35 +02002978 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci33090f92020-12-17 20:12:46 +01002979 LY_CHECK_RET(parse_restrs(ctx, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002980 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002981 case LY_STMT_TYPEDEF:
Radek Krejci33090f92020-12-17 20:12:46 +01002982 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)notif, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002983 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002984 case LY_STMT_GROUPING:
Radek Krejci33090f92020-12-17 20:12:46 +01002985 LY_CHECK_RET(parse_grouping(ctx, (struct lysp_node *)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002986 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002987 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01002988 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_NOTIFICATION, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002989 break;
2990 default:
David Sedlákb3077192019-06-19 10:55:37 +02002991 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002992 return LY_EVALID;
2993 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002994 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002995
Michal Vasko12ef5362022-09-16 15:13:58 +02002996cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002997 return ret;
2998}
2999
Michal Vaskoea5abea2018-09-18 13:10:54 +02003000/**
3001 * @brief Parse the grouping statement.
3002 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003003 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003004 * @param[in,out] groupings Groupings to add to.
3005 *
3006 * @return LY_ERR values.
3007 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003008LY_ERR
Radek Krejci2a9fc652021-01-22 17:44:34 +01003009parse_grouping(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003010{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003011 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003012 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003013 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003014 enum ly_stmt kw;
Radek Krejci2a9fc652021-01-22 17:44:34 +01003015 struct lysp_node_grp *grp;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003016
Radek Krejci2a9fc652021-01-22 17:44:34 +01003017 LY_LIST_NEW_RET(PARSER_CTX(ctx), groupings, grp, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003018
3019 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01003020 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02003021 INSERT_WORD_GOTO(ctx, buf, grp->name, word, word_len, ret, cleanup);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003022 grp->nodetype = LYS_GROUPING;
3023 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003024
aPiecek63e080d2021-06-29 13:53:28 +02003025 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003026 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003027 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01003028 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003029 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003030 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003031 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003033 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01003034 LY_CHECK_RET(parse_status(ctx, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003035 break;
3036
Radek Krejcid6b76452019-09-03 17:03:03 +02003037 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003038 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci0f969882020-08-21 16:56:47 +02003039 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003040 case LY_STMT_ANYXML:
Radek Krejci01180ac2021-01-27 08:48:22 +01003041 LY_CHECK_RET(parse_any(ctx, kw, &grp->node, &grp->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003042 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003043 case LY_STMT_CHOICE:
Radek Krejci01180ac2021-01-27 08:48:22 +01003044 LY_CHECK_RET(parse_choice(ctx, &grp->node, &grp->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003045 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003046 case LY_STMT_CONTAINER:
Radek Krejci01180ac2021-01-27 08:48:22 +01003047 LY_CHECK_RET(parse_container(ctx, &grp->node, &grp->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003048 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003049 case LY_STMT_LEAF:
Radek Krejci01180ac2021-01-27 08:48:22 +01003050 LY_CHECK_RET(parse_leaf(ctx, &grp->node, &grp->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003051 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003052 case LY_STMT_LEAF_LIST:
Radek Krejci01180ac2021-01-27 08:48:22 +01003053 LY_CHECK_RET(parse_leaflist(ctx, &grp->node, &grp->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003054 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003055 case LY_STMT_LIST:
Radek Krejci01180ac2021-01-27 08:48:22 +01003056 LY_CHECK_RET(parse_list(ctx, &grp->node, &grp->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003057 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003058 case LY_STMT_USES:
Radek Krejci01180ac2021-01-27 08:48:22 +01003059 LY_CHECK_RET(parse_uses(ctx, &grp->node, &grp->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003060 break;
3061
Radek Krejcid6b76452019-09-03 17:03:03 +02003062 case LY_STMT_TYPEDEF:
Radek Krejci2a9fc652021-01-22 17:44:34 +01003063 LY_CHECK_RET(parse_typedef(ctx, &grp->node, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003064 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003065 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02003066 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci2a9fc652021-01-22 17:44:34 +01003067 LY_CHECK_RET(parse_action(ctx, &grp->node, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003068 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003069 case LY_STMT_GROUPING:
Radek Krejci2a9fc652021-01-22 17:44:34 +01003070 LY_CHECK_RET(parse_grouping(ctx, &grp->node, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003071 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003072 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02003073 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci2a9fc652021-01-22 17:44:34 +01003074 LY_CHECK_RET(parse_notif(ctx, &grp->node, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003075 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003076 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003077 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_GROUPING, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003078 break;
3079 default:
David Sedlákb3077192019-06-19 10:55:37 +02003080 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003081 return LY_EVALID;
3082 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003083 }
aPiecek63e080d2021-06-29 13:53:28 +02003084 LY_CHECK_RET(ret);
Michal Vasko12ef5362022-09-16 15:13:58 +02003085
aPiecek63e080d2021-06-29 13:53:28 +02003086checks:
3087 /* store data for collision check */
3088 if (parent) {
3089 assert(ctx->main_ctx);
3090 LY_CHECK_RET(ly_set_add(&ctx->main_ctx->grps_nodes, parent, 0, NULL));
3091 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003092
Michal Vasko12ef5362022-09-16 15:13:58 +02003093cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003094 return ret;
3095}
3096
Michal Vaskoea5abea2018-09-18 13:10:54 +02003097/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02003098 * @brief Parse the augment statement.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003099 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003100 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003101 * @param[in,out] augments Augments to add to.
3102 *
3103 * @return LY_ERR values.
3104 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003105LY_ERR
Radek Krejci2a9fc652021-01-22 17:44:34 +01003106parse_augment(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003107{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003108 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003109 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003110 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003111 enum ly_stmt kw;
Radek Krejci2a9fc652021-01-22 17:44:34 +01003112 struct lysp_node_augment *aug;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003113
Radek Krejci2a9fc652021-01-22 17:44:34 +01003114 LY_LIST_NEW_RET(PARSER_CTX(ctx), augments, aug, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003115
3116 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01003117 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vaskob36053d2020-03-26 15:49:30 +01003118 CHECK_NONEMPTY(ctx, word_len, "augment");
Michal Vasko12ef5362022-09-16 15:13:58 +02003119 INSERT_WORD_GOTO(ctx, buf, aug->nodeid, word, word_len, ret, cleanup);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003120 aug->nodetype = LYS_AUGMENT;
3121 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003122
aPieceka24a2252021-05-07 10:52:31 +02003123 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003124 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003125 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01003126 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003127 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003128 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003129 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003130 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003131 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003132 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003133 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003134 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01003135 LY_CHECK_RET(parse_status(ctx, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003136 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003137 case LY_STMT_WHEN:
Radek Krejci33090f92020-12-17 20:12:46 +01003138 LY_CHECK_RET(parse_when(ctx, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003139 break;
3140
Radek Krejcid6b76452019-09-03 17:03:03 +02003141 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003142 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci0f969882020-08-21 16:56:47 +02003143 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003144 case LY_STMT_ANYXML:
Radek Krejci33090f92020-12-17 20:12:46 +01003145 LY_CHECK_RET(parse_any(ctx, kw, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003146 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003147 case LY_STMT_CASE:
Radek Krejci33090f92020-12-17 20:12:46 +01003148 LY_CHECK_RET(parse_case(ctx, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003149 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003150 case LY_STMT_CHOICE:
Radek Krejci33090f92020-12-17 20:12:46 +01003151 LY_CHECK_RET(parse_choice(ctx, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003152 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003153 case LY_STMT_CONTAINER:
Radek Krejci33090f92020-12-17 20:12:46 +01003154 LY_CHECK_RET(parse_container(ctx, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003155 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003156 case LY_STMT_LEAF:
Radek Krejci33090f92020-12-17 20:12:46 +01003157 LY_CHECK_RET(parse_leaf(ctx, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003158 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003159 case LY_STMT_LEAF_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01003160 LY_CHECK_RET(parse_leaflist(ctx, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003161 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003162 case LY_STMT_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01003163 LY_CHECK_RET(parse_list(ctx, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003164 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003165 case LY_STMT_USES:
Radek Krejci33090f92020-12-17 20:12:46 +01003166 LY_CHECK_RET(parse_uses(ctx, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003167 break;
3168
Radek Krejcid6b76452019-09-03 17:03:03 +02003169 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02003170 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci33090f92020-12-17 20:12:46 +01003171 LY_CHECK_RET(parse_action(ctx, (struct lysp_node *)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003172 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003173 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02003174 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci33090f92020-12-17 20:12:46 +01003175 LY_CHECK_RET(parse_notif(ctx, (struct lysp_node *)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003176 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003177 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003178 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_AUGMENT, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003179 break;
3180 default:
David Sedlákb3077192019-06-19 10:55:37 +02003181 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003182 return LY_EVALID;
3183 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003184 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003185
Michal Vasko12ef5362022-09-16 15:13:58 +02003186cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003187 return ret;
3188}
3189
Michal Vaskoea5abea2018-09-18 13:10:54 +02003190/**
3191 * @brief Parse the uses statement.
3192 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003193 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003194 * @param[in,out] siblings Siblings to add to.
3195 *
3196 * @return LY_ERR values.
3197 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003198LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01003199parse_uses(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003200{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003201 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003202 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003203 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003204 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003205 struct lysp_node_uses *uses;
3206
David Sedlák60adc092019-08-06 15:57:02 +02003207 /* create uses structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003208 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003209 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003210 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003211
Michal Vasko7fbc8162018-09-17 10:35:16 +02003212 /* get name */
Radek Krejci33090f92020-12-17 20:12:46 +01003213 LY_CHECK_RET(get_argument(ctx, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02003214 INSERT_WORD_GOTO(ctx, buf, uses->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003215
3216 /* parse substatements */
aPieceka24a2252021-05-07 10:52:31 +02003217 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003218 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003219 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01003220 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003221 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003222 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003223 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003225 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003226 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003227 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003228 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01003229 LY_CHECK_RET(parse_status(ctx, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003230 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003231 case LY_STMT_WHEN:
Radek Krejci33090f92020-12-17 20:12:46 +01003232 LY_CHECK_RET(parse_when(ctx, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003233 break;
3234
Radek Krejcid6b76452019-09-03 17:03:03 +02003235 case LY_STMT_REFINE:
Radek Krejci33090f92020-12-17 20:12:46 +01003236 LY_CHECK_RET(parse_refine(ctx, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003237 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003238 case LY_STMT_AUGMENT:
Radek Krejci33090f92020-12-17 20:12:46 +01003239 LY_CHECK_RET(parse_augment(ctx, (struct lysp_node *)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003240 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003241 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003242 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_USES, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003243 break;
3244 default:
David Sedlákb3077192019-06-19 10:55:37 +02003245 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003246 return LY_EVALID;
3247 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003248 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003249
Michal Vasko12ef5362022-09-16 15:13:58 +02003250cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003251 return ret;
3252}
3253
Michal Vaskoea5abea2018-09-18 13:10:54 +02003254/**
3255 * @brief Parse the case statement.
3256 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003257 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003258 * @param[in,out] siblings Siblings to add to.
3259 *
3260 * @return LY_ERR values.
3261 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003262LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01003263parse_case(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003264{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003265 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003266 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003267 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003268 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003269 struct lysp_node_case *cas;
3270
David Sedlák60adc092019-08-06 15:57:02 +02003271 /* create new case structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003272 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003273 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003274 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003275
Michal Vasko7fbc8162018-09-17 10:35:16 +02003276 /* get name */
Radek Krejci33090f92020-12-17 20:12:46 +01003277 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02003278 INSERT_WORD_GOTO(ctx, buf, cas->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003279
3280 /* parse substatements */
aPieceka24a2252021-05-07 10:52:31 +02003281 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003282 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003283 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01003284 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003285 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003286 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003287 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003288 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003289 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003290 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003291 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003292 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01003293 LY_CHECK_RET(parse_status(ctx, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003294 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003295 case LY_STMT_WHEN:
Radek Krejci33090f92020-12-17 20:12:46 +01003296 LY_CHECK_RET(parse_when(ctx, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297 break;
3298
Radek Krejcid6b76452019-09-03 17:03:03 +02003299 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003300 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci0f969882020-08-21 16:56:47 +02003301 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003302 case LY_STMT_ANYXML:
Radek Krejci33090f92020-12-17 20:12:46 +01003303 LY_CHECK_RET(parse_any(ctx, kw, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003304 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003305 case LY_STMT_CHOICE:
Radek Krejci33090f92020-12-17 20:12:46 +01003306 LY_CHECK_RET(parse_choice(ctx, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003307 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003308 case LY_STMT_CONTAINER:
Radek Krejci33090f92020-12-17 20:12:46 +01003309 LY_CHECK_RET(parse_container(ctx, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003310 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003311 case LY_STMT_LEAF:
Radek Krejci33090f92020-12-17 20:12:46 +01003312 LY_CHECK_RET(parse_leaf(ctx, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003313 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003314 case LY_STMT_LEAF_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01003315 LY_CHECK_RET(parse_leaflist(ctx, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003316 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003317 case LY_STMT_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01003318 LY_CHECK_RET(parse_list(ctx, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003319 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003320 case LY_STMT_USES:
Radek Krejci33090f92020-12-17 20:12:46 +01003321 LY_CHECK_RET(parse_uses(ctx, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003322 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003323 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003324 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_CASE, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003325 break;
3326 default:
David Sedlákb3077192019-06-19 10:55:37 +02003327 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003328 return LY_EVALID;
3329 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003330 }
Michal Vasko12ef5362022-09-16 15:13:58 +02003331
3332cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003333 return ret;
3334}
3335
Michal Vaskoea5abea2018-09-18 13:10:54 +02003336/**
3337 * @brief Parse the choice statement.
3338 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003339 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003340 * @param[in,out] siblings Siblings to add to.
3341 *
3342 * @return LY_ERR values.
3343 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003344LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01003345parse_choice(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003346{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003347 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003348 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003349 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003350 enum ly_stmt kw;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003351 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003352
David Sedlák60adc092019-08-06 15:57:02 +02003353 /* create new choice structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003354 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003355 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003356 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003357
Michal Vasko7fbc8162018-09-17 10:35:16 +02003358 /* get name */
Radek Krejci33090f92020-12-17 20:12:46 +01003359 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02003360 INSERT_WORD_GOTO(ctx, buf, choice->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003361
3362 /* parse substatements */
aPieceka24a2252021-05-07 10:52:31 +02003363 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003364 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003365 case LY_STMT_CONFIG:
Radek Krejci33090f92020-12-17 20:12:46 +01003366 LY_CHECK_RET(parse_config(ctx, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003367 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003368 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01003369 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003370 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003371 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003372 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003373 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003374 case LY_STMT_MANDATORY:
Radek Krejci33090f92020-12-17 20:12:46 +01003375 LY_CHECK_RET(parse_mandatory(ctx, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003376 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003377 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003378 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003379 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003380 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01003381 LY_CHECK_RET(parse_status(ctx, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003382 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003383 case LY_STMT_WHEN:
Radek Krejci33090f92020-12-17 20:12:46 +01003384 LY_CHECK_RET(parse_when(ctx, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003385 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003386 case LY_STMT_DEFAULT:
Radek Krejcifc596f92021-02-26 22:40:26 +01003387 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DEFAULT, 0, &choice->dflt.str, Y_PREF_IDENTIF_ARG,
Michal Vasko7f45cf22020-10-01 12:49:44 +02003388 &choice->exts));
Michal Vasko8a67eff2021-12-07 14:04:47 +01003389 choice->dflt.mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003390 break;
3391
Radek Krejcid6b76452019-09-03 17:03:03 +02003392 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003393 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci0f969882020-08-21 16:56:47 +02003394 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003395 case LY_STMT_ANYXML:
Radek Krejci33090f92020-12-17 20:12:46 +01003396 LY_CHECK_RET(parse_any(ctx, kw, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003397 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003398 case LY_STMT_CASE:
Radek Krejci33090f92020-12-17 20:12:46 +01003399 LY_CHECK_RET(parse_case(ctx, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003400 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003401 case LY_STMT_CHOICE:
Radek Krejci335332a2019-09-05 13:03:35 +02003402 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci33090f92020-12-17 20:12:46 +01003403 LY_CHECK_RET(parse_choice(ctx, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003404 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003405 case LY_STMT_CONTAINER:
Radek Krejci33090f92020-12-17 20:12:46 +01003406 LY_CHECK_RET(parse_container(ctx, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003407 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003408 case LY_STMT_LEAF:
Radek Krejci33090f92020-12-17 20:12:46 +01003409 LY_CHECK_RET(parse_leaf(ctx, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003410 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003411 case LY_STMT_LEAF_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01003412 LY_CHECK_RET(parse_leaflist(ctx, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003413 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003414 case LY_STMT_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01003415 LY_CHECK_RET(parse_list(ctx, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003416 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003417 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003418 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_CHOICE, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003419 break;
3420 default:
David Sedlákb3077192019-06-19 10:55:37 +02003421 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003422 return LY_EVALID;
3423 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003424 }
Michal Vasko12ef5362022-09-16 15:13:58 +02003425
3426cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003427 return ret;
3428}
3429
Michal Vaskoea5abea2018-09-18 13:10:54 +02003430/**
3431 * @brief Parse the container statement.
3432 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003433 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003434 * @param[in,out] siblings Siblings to add to.
3435 *
3436 * @return LY_ERR values.
3437 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003438LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01003439parse_container(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003440{
3441 LY_ERR ret = 0;
3442 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003443 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003444 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003445 struct lysp_node_container *cont;
3446
David Sedlák60adc092019-08-06 15:57:02 +02003447 /* create new container structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003448 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003449 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003450 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003451
Michal Vasko7fbc8162018-09-17 10:35:16 +02003452 /* get name */
Radek Krejci33090f92020-12-17 20:12:46 +01003453 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02003454 INSERT_WORD_GOTO(ctx, buf, cont->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003455
3456 /* parse substatements */
aPieceka24a2252021-05-07 10:52:31 +02003457 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003458 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003459 case LY_STMT_CONFIG:
Radek Krejci33090f92020-12-17 20:12:46 +01003460 LY_CHECK_RET(parse_config(ctx, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003461 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003462 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01003463 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003464 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003465 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003466 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003467 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003468 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003469 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003470 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003471 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01003472 LY_CHECK_RET(parse_status(ctx, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003473 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003474 case LY_STMT_WHEN:
Radek Krejci33090f92020-12-17 20:12:46 +01003475 LY_CHECK_RET(parse_when(ctx, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003476 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003477 case LY_STMT_PRESENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003478 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003479 break;
3480
Radek Krejcid6b76452019-09-03 17:03:03 +02003481 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003482 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci0f969882020-08-21 16:56:47 +02003483 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003484 case LY_STMT_ANYXML:
Radek Krejci33090f92020-12-17 20:12:46 +01003485 LY_CHECK_RET(parse_any(ctx, kw, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003486 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003487 case LY_STMT_CHOICE:
Radek Krejci33090f92020-12-17 20:12:46 +01003488 LY_CHECK_RET(parse_choice(ctx, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003489 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003490 case LY_STMT_CONTAINER:
Radek Krejci33090f92020-12-17 20:12:46 +01003491 LY_CHECK_RET(parse_container(ctx, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003492 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003493 case LY_STMT_LEAF:
Radek Krejci33090f92020-12-17 20:12:46 +01003494 LY_CHECK_RET(parse_leaf(ctx, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003495 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003496 case LY_STMT_LEAF_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01003497 LY_CHECK_RET(parse_leaflist(ctx, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003498 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003499 case LY_STMT_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01003500 LY_CHECK_RET(parse_list(ctx, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003501 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003502 case LY_STMT_USES:
Radek Krejci33090f92020-12-17 20:12:46 +01003503 LY_CHECK_RET(parse_uses(ctx, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003504 break;
3505
Radek Krejcid6b76452019-09-03 17:03:03 +02003506 case LY_STMT_TYPEDEF:
Radek Krejci33090f92020-12-17 20:12:46 +01003507 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)cont, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003508 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003509 case LY_STMT_MUST:
Radek Krejci33090f92020-12-17 20:12:46 +01003510 LY_CHECK_RET(parse_restrs(ctx, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003511 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003512 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02003513 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci33090f92020-12-17 20:12:46 +01003514 LY_CHECK_RET(parse_action(ctx, (struct lysp_node *)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003515 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003516 case LY_STMT_GROUPING:
Radek Krejci33090f92020-12-17 20:12:46 +01003517 LY_CHECK_RET(parse_grouping(ctx, (struct lysp_node *)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003518 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003519 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02003520 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci33090f92020-12-17 20:12:46 +01003521 LY_CHECK_RET(parse_notif(ctx, (struct lysp_node *)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003522 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003523 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003524 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_CONTAINER, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003525 break;
3526 default:
David Sedlákb3077192019-06-19 10:55:37 +02003527 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003528 return LY_EVALID;
3529 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530 }
Radek Krejci2a9fc652021-01-22 17:44:34 +01003531
Michal Vasko12ef5362022-09-16 15:13:58 +02003532cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003533 return ret;
3534}
3535
Michal Vaskoea5abea2018-09-18 13:10:54 +02003536/**
3537 * @brief Parse the list statement.
3538 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003539 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003540 * @param[in,out] siblings Siblings to add to.
3541 *
3542 * @return LY_ERR values.
3543 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003544LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01003545parse_list(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003546{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003547 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003548 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003549 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003550 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003551 struct lysp_node_list *list;
3552
David Sedlák60adc092019-08-06 15:57:02 +02003553 /* create new list structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003554 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003555 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003556 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003557
Michal Vasko7fbc8162018-09-17 10:35:16 +02003558 /* get name */
Radek Krejci33090f92020-12-17 20:12:46 +01003559 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02003560 INSERT_WORD_GOTO(ctx, buf, list->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003561
3562 /* parse substatements */
aPieceka24a2252021-05-07 10:52:31 +02003563 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003564 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003565 case LY_STMT_CONFIG:
Radek Krejci33090f92020-12-17 20:12:46 +01003566 LY_CHECK_RET(parse_config(ctx, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003567 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003568 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01003569 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003570 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003571 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003572 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &list->iffeatures, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003573 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003574 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003575 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003576 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003577 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01003578 LY_CHECK_RET(parse_status(ctx, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003579 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003580 case LY_STMT_WHEN:
Radek Krejci33090f92020-12-17 20:12:46 +01003581 LY_CHECK_RET(parse_when(ctx, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003582 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003583 case LY_STMT_KEY:
Radek Krejcifc596f92021-02-26 22:40:26 +01003584 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003585 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003586 case LY_STMT_MAX_ELEMENTS:
Radek Krejci33090f92020-12-17 20:12:46 +01003587 LY_CHECK_RET(parse_maxelements(ctx, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003588 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003589 case LY_STMT_MIN_ELEMENTS:
Radek Krejci33090f92020-12-17 20:12:46 +01003590 LY_CHECK_RET(parse_minelements(ctx, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003591 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003592 case LY_STMT_ORDERED_BY:
Radek Krejci33090f92020-12-17 20:12:46 +01003593 LY_CHECK_RET(parse_orderedby(ctx, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003594 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003595 case LY_STMT_UNIQUE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003596 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003597 break;
3598
Radek Krejcid6b76452019-09-03 17:03:03 +02003599 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003600 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci0f969882020-08-21 16:56:47 +02003601 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003602 case LY_STMT_ANYXML:
Radek Krejci33090f92020-12-17 20:12:46 +01003603 LY_CHECK_RET(parse_any(ctx, kw, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003604 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003605 case LY_STMT_CHOICE:
Radek Krejci33090f92020-12-17 20:12:46 +01003606 LY_CHECK_RET(parse_choice(ctx, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003607 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003608 case LY_STMT_CONTAINER:
Radek Krejci33090f92020-12-17 20:12:46 +01003609 LY_CHECK_RET(parse_container(ctx, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003611 case LY_STMT_LEAF:
Radek Krejci33090f92020-12-17 20:12:46 +01003612 LY_CHECK_RET(parse_leaf(ctx, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003613 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003614 case LY_STMT_LEAF_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01003615 LY_CHECK_RET(parse_leaflist(ctx, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003616 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003617 case LY_STMT_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01003618 LY_CHECK_RET(parse_list(ctx, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003619 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003620 case LY_STMT_USES:
Radek Krejci33090f92020-12-17 20:12:46 +01003621 LY_CHECK_RET(parse_uses(ctx, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003622 break;
3623
Radek Krejcid6b76452019-09-03 17:03:03 +02003624 case LY_STMT_TYPEDEF:
Radek Krejci33090f92020-12-17 20:12:46 +01003625 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)list, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003626 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003627 case LY_STMT_MUST:
Radek Krejci33090f92020-12-17 20:12:46 +01003628 LY_CHECK_RET(parse_restrs(ctx, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003629 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003630 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02003631 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci33090f92020-12-17 20:12:46 +01003632 LY_CHECK_RET(parse_action(ctx, (struct lysp_node *)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003633 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003634 case LY_STMT_GROUPING:
Radek Krejci33090f92020-12-17 20:12:46 +01003635 LY_CHECK_RET(parse_grouping(ctx, (struct lysp_node *)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003636 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003637 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02003638 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci33090f92020-12-17 20:12:46 +01003639 LY_CHECK_RET(parse_notif(ctx, (struct lysp_node *)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003640 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003641 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003642 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_LIST, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643 break;
3644 default:
David Sedlákb3077192019-06-19 10:55:37 +02003645 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003646 return LY_EVALID;
3647 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003648 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003649
Michal Vasko12ef5362022-09-16 15:13:58 +02003650cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003651 return ret;
3652}
3653
Michal Vaskoea5abea2018-09-18 13:10:54 +02003654/**
3655 * @brief Parse the yin-element statement.
3656 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003657 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003658 * @param[in,out] flags Flags to write to.
3659 * @param[in,out] exts Extension instances to add to.
3660 *
3661 * @return LY_ERR values.
3662 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003663static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01003664parse_yinelement(struct lys_yang_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003665{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003666 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003667 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003668 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003669 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003670
3671 if (*flags & LYS_YINELEM_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02003672 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003673 return LY_EVALID;
3674 }
3675
3676 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01003677 LY_CHECK_RET(get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003678
Radek Krejcif13b87b2020-12-01 22:02:17 +01003679 if ((word_len == ly_strlen_const("true")) && !strncmp(word, "true", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003680 *flags |= LYS_YINELEM_TRUE;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003681 } else if ((word_len == ly_strlen_const("false")) && !strncmp(word, "false", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003682 *flags |= LYS_YINELEM_FALSE;
3683 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003684 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003685 free(buf);
3686 return LY_EVALID;
3687 }
3688 free(buf);
3689
aPieceka24a2252021-05-07 10:52:31 +02003690 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003691 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003692 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003693 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_YIN_ELEMENT, 0, exts));
Michal Vaskod989ba02020-08-24 10:59:24 +02003694 LY_CHECK_RET(ret);
3695 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003696 default:
David Sedlákb3077192019-06-19 10:55:37 +02003697 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003698 return LY_EVALID;
3699 }
3700 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003701 return ret;
3702}
3703
Michal Vaskoea5abea2018-09-18 13:10:54 +02003704/**
David Sedlák2444f8f2019-07-09 11:02:47 +02003705 * @brief Parse the argument statement.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003706 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003707 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003708 * @param[in,out] argument Value to write to.
3709 * @param[in,out] flags Flags to write to.
3710 * @param[in,out] exts Extension instances to add to.
3711 *
3712 * @return LY_ERR values.
3713 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003714static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01003715parse_argument(struct lys_yang_parser_ctx *ctx, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003716{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003717 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003718 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003719 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003720 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003721
3722 if (*argument) {
David Sedlákb3077192019-06-19 10:55:37 +02003723 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003724 return LY_EVALID;
3725 }
3726
3727 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01003728 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02003729 INSERT_WORD_GOTO(ctx, buf, *argument, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003730
aPieceka24a2252021-05-07 10:52:31 +02003731 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003732 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003733 case LY_STMT_YIN_ELEMENT:
Radek Krejci33090f92020-12-17 20:12:46 +01003734 LY_CHECK_RET(parse_yinelement(ctx, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003735 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003736 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003737 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003738 break;
3739 default:
David Sedlákb3077192019-06-19 10:55:37 +02003740 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003741 return LY_EVALID;
3742 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003743 }
Michal Vasko12ef5362022-09-16 15:13:58 +02003744
3745cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003746 return ret;
3747}
3748
Michal Vaskoea5abea2018-09-18 13:10:54 +02003749/**
3750 * @brief Parse the extension statement.
3751 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003752 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003753 * @param[in,out] extensions Extensions to add to.
3754 *
3755 * @return LY_ERR values.
3756 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003757static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01003758parse_extension(struct lys_yang_parser_ctx *ctx, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003759{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003760 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003761 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003762 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003763 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003764 struct lysp_ext *ex;
3765
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003766 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003767
3768 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01003769 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02003770 INSERT_WORD_GOTO(ctx, buf, ex->name, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003771
aPieceka24a2252021-05-07 10:52:31 +02003772 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003773 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003774 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01003775 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003776 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003777 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01003778 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003779 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003780 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01003781 LY_CHECK_RET(parse_status(ctx, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003782 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003783 case LY_STMT_ARGUMENT:
Radek Krejci9f87b0c2021-03-05 14:45:26 +01003784 LY_CHECK_RET(parse_argument(ctx, &ex->argname, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003785 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003786 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003787 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_EXTENSION, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003788 break;
3789 default:
David Sedlákb3077192019-06-19 10:55:37 +02003790 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003791 return LY_EVALID;
3792 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003793 }
Michal Vasko12ef5362022-09-16 15:13:58 +02003794
3795cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003796 return ret;
3797}
3798
Michal Vaskoea5abea2018-09-18 13:10:54 +02003799/**
3800 * @brief Parse the deviate statement.
3801 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003802 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003803 * @param[in,out] deviates Deviates to add to.
3804 *
3805 * @return LY_ERR values.
3806 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003807LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01003808parse_deviate(struct lys_yang_parser_ctx *ctx, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003809{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003810 LY_ERR ret = LY_SUCCESS;
Michal Vasko12ef5362022-09-16 15:13:58 +02003811 char *buf = NULL, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003812 size_t word_len, dev_mod;
Radek Krejcid6b76452019-09-03 17:03:03 +02003813 enum ly_stmt kw;
Michal Vaskoc636ea42022-09-16 10:20:31 +02003814 struct lysf_ctx fctx = {.ctx = PARSER_CTX(ctx)};
Michal Vasko12ef5362022-09-16 15:13:58 +02003815 struct lysp_deviate *d = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003816 struct lysp_deviate_add *d_add = NULL;
3817 struct lysp_deviate_rpl *d_rpl = NULL;
3818 struct lysp_deviate_del *d_del = NULL;
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003819 const char **d_units = NULL;
3820 struct lysp_qname **d_uniques = NULL, **d_dflts = NULL;
Radek Krejci4ad42aa2019-07-23 16:55:58 +02003821 struct lysp_restr **d_musts = NULL;
3822 uint16_t *d_flags = 0;
3823 uint32_t *d_min = 0, *d_max = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003824
3825 /* get value */
Michal Vasko12ef5362022-09-16 15:13:58 +02003826 LY_CHECK_GOTO(ret = get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003827
Radek Krejcif13b87b2020-12-01 22:02:17 +01003828 if ((word_len == ly_strlen_const("not-supported")) && !strncmp(word, "not-supported", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003829 dev_mod = LYS_DEV_NOT_SUPPORTED;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003830 } else if ((word_len == ly_strlen_const("add")) && !strncmp(word, "add", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003831 dev_mod = LYS_DEV_ADD;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003832 } else if ((word_len == ly_strlen_const("replace")) && !strncmp(word, "replace", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003833 dev_mod = LYS_DEV_REPLACE;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003834 } else if ((word_len == ly_strlen_const("delete")) && !strncmp(word, "delete", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003835 dev_mod = LYS_DEV_DELETE;
3836 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003837 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko12ef5362022-09-16 15:13:58 +02003838 ret = LY_EVALID;
3839 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003840 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003841
3842 /* create structure */
3843 switch (dev_mod) {
3844 case LYS_DEV_NOT_SUPPORTED:
3845 d = calloc(1, sizeof *d);
Michal Vasko12ef5362022-09-16 15:13:58 +02003846 LY_CHECK_ERR_GOTO(!d, LOGMEM(PARSER_CTX(ctx)); ret = LY_EMEM, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003847 break;
3848 case LYS_DEV_ADD:
3849 d_add = calloc(1, sizeof *d_add);
Michal Vasko12ef5362022-09-16 15:13:58 +02003850 LY_CHECK_ERR_GOTO(!d_add, LOGMEM(PARSER_CTX(ctx)); ret = LY_EMEM, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003851 d = (struct lysp_deviate *)d_add;
3852 d_units = &d_add->units;
3853 d_uniques = &d_add->uniques;
3854 d_dflts = &d_add->dflts;
3855 d_musts = &d_add->musts;
3856 d_flags = &d_add->flags;
3857 d_min = &d_add->min;
3858 d_max = &d_add->max;
3859 break;
3860 case LYS_DEV_REPLACE:
3861 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vasko12ef5362022-09-16 15:13:58 +02003862 LY_CHECK_ERR_GOTO(!d_rpl, LOGMEM(PARSER_CTX(ctx)); ret = LY_EMEM, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003863 d = (struct lysp_deviate *)d_rpl;
3864 d_units = &d_rpl->units;
3865 d_flags = &d_rpl->flags;
3866 d_min = &d_rpl->min;
3867 d_max = &d_rpl->max;
3868 break;
3869 case LYS_DEV_DELETE:
3870 d_del = calloc(1, sizeof *d_del);
Michal Vasko12ef5362022-09-16 15:13:58 +02003871 LY_CHECK_ERR_GOTO(!d_del, LOGMEM(PARSER_CTX(ctx)); ret = LY_EMEM, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003872 d = (struct lysp_deviate *)d_del;
3873 d_units = &d_del->units;
3874 d_uniques = &d_del->uniques;
3875 d_dflts = &d_del->dflts;
3876 d_musts = &d_del->musts;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003877 break;
3878 default:
3879 assert(0);
Michal Vasko12ef5362022-09-16 15:13:58 +02003880 LOGINT(PARSER_CTX(ctx));
3881 ret = LY_EINT;
3882 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003883 }
3884 d->mod = dev_mod;
3885
Michal Vasko12ef5362022-09-16 15:13:58 +02003886 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto cleanup, goto cleanup) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003887 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003888 case LY_STMT_CONFIG:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003889 switch (dev_mod) {
3890 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003891 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003892 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko12ef5362022-09-16 15:13:58 +02003893 ret = LY_EVALID;
3894 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003895 default:
Michal Vasko12ef5362022-09-16 15:13:58 +02003896 LY_CHECK_GOTO(ret = parse_config(ctx, d_flags, &d->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003897 break;
3898 }
3899 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003900 case LY_STMT_DEFAULT:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003901 switch (dev_mod) {
3902 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02003903 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko12ef5362022-09-16 15:13:58 +02003904 ret = LY_EVALID;
3905 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003906 case LYS_DEV_REPLACE:
Michal Vasko12ef5362022-09-16 15:13:58 +02003907 LY_CHECK_GOTO(ret = parse_text_field(ctx, LY_STMT_DEFAULT, 0, &d_rpl->dflt.str, Y_STR_ARG, &d->exts), cleanup);
Michal Vasko8a67eff2021-12-07 14:04:47 +01003908 d_rpl->dflt.mod = PARSER_CUR_PMOD(ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003909 break;
3910 default:
Michal Vasko12ef5362022-09-16 15:13:58 +02003911 LY_CHECK_GOTO(ret = parse_qnames(ctx, LY_STMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003912 break;
3913 }
3914 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003915 case LY_STMT_MANDATORY:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003916 switch (dev_mod) {
3917 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003918 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003919 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko12ef5362022-09-16 15:13:58 +02003920 ret = LY_EVALID;
3921 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 default:
Michal Vasko12ef5362022-09-16 15:13:58 +02003923 LY_CHECK_GOTO(ret = parse_mandatory(ctx, d_flags, &d->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003924 break;
3925 }
3926 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003927 case LY_STMT_MAX_ELEMENTS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003928 switch (dev_mod) {
3929 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003930 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003931 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko12ef5362022-09-16 15:13:58 +02003932 ret = LY_EVALID;
3933 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003934 default:
Michal Vasko12ef5362022-09-16 15:13:58 +02003935 LY_CHECK_GOTO(ret = parse_maxelements(ctx, d_max, d_flags, &d->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003936 break;
3937 }
3938 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003939 case LY_STMT_MIN_ELEMENTS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003940 switch (dev_mod) {
3941 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003942 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003943 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko12ef5362022-09-16 15:13:58 +02003944 ret = LY_EVALID;
3945 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003946 default:
Michal Vasko12ef5362022-09-16 15:13:58 +02003947 LY_CHECK_GOTO(ret = parse_minelements(ctx, d_min, d_flags, &d->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003948 break;
3949 }
3950 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003951 case LY_STMT_MUST:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003952 switch (dev_mod) {
3953 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003954 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02003955 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko12ef5362022-09-16 15:13:58 +02003956 ret = LY_EVALID;
3957 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003958 default:
Michal Vasko12ef5362022-09-16 15:13:58 +02003959 LY_CHECK_GOTO(ret = parse_restrs(ctx, kw, d_musts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003960 break;
3961 }
3962 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003963 case LY_STMT_TYPE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003964 switch (dev_mod) {
3965 case LYS_DEV_NOT_SUPPORTED:
3966 case LYS_DEV_ADD:
3967 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003968 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko12ef5362022-09-16 15:13:58 +02003969 ret = LY_EVALID;
3970 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003971 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003972 if (d_rpl->type) {
David Sedlákb3077192019-06-19 10:55:37 +02003973 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko12ef5362022-09-16 15:13:58 +02003974 ret = LY_EVALID;
3975 goto cleanup;
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003976 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003977 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Michal Vasko12ef5362022-09-16 15:13:58 +02003978 LY_CHECK_ERR_GOTO(!d_rpl->type, LOGMEM(PARSER_CTX(ctx)); ret = LY_EMEM, cleanup);
3979 LY_CHECK_GOTO(ret = parse_type(ctx, d_rpl->type), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003980 break;
3981 }
3982 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003983 case LY_STMT_UNIQUE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003984 switch (dev_mod) {
3985 case LYS_DEV_NOT_SUPPORTED:
3986 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02003987 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko12ef5362022-09-16 15:13:58 +02003988 ret = LY_EVALID;
3989 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003990 default:
Michal Vasko12ef5362022-09-16 15:13:58 +02003991 LY_CHECK_GOTO(ret = parse_qnames(ctx, LY_STMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003992 break;
3993 }
3994 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003995 case LY_STMT_UNITS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003996 switch (dev_mod) {
3997 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02003998 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko12ef5362022-09-16 15:13:58 +02003999 ret = LY_EVALID;
4000 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004001 default:
Michal Vasko12ef5362022-09-16 15:13:58 +02004002 LY_CHECK_GOTO(ret = parse_text_field(ctx, LY_STMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004003 break;
4004 }
4005 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004006 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko12ef5362022-09-16 15:13:58 +02004007 LY_CHECK_GOTO(ret = parse_ext(ctx, word, word_len, LY_STMT_DEVIATE, 0, &d->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004008 break;
4009 default:
David Sedlákb3077192019-06-19 10:55:37 +02004010 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko12ef5362022-09-16 15:13:58 +02004011 ret = LY_EVALID;
4012 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004013 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004014 }
Michal Vasko12ef5362022-09-16 15:13:58 +02004015
4016cleanup:
4017 free(buf);
4018 if (ret) {
Michal Vaskoc636ea42022-09-16 10:20:31 +02004019 lysp_deviate_free(&fctx, d);
Michal Vasko12ef5362022-09-16 15:13:58 +02004020 free(d);
4021 } else {
4022 /* insert into siblings */
4023 LY_LIST_INSERT(deviates, d, next);
4024 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004025 return ret;
4026}
4027
Michal Vaskoea5abea2018-09-18 13:10:54 +02004028/**
4029 * @brief Parse the deviation statement.
4030 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004031 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004032 * @param[in,out] deviations Deviations to add to.
4033 *
4034 * @return LY_ERR values.
4035 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004036LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01004037parse_deviation(struct lys_yang_parser_ctx *ctx, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004038{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004039 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004040 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004041 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004042 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004043 struct lysp_deviation *dev;
Michal Vaskoc636ea42022-09-16 10:20:31 +02004044 struct lysf_ctx fctx = {.ctx = PARSER_CTX(ctx)};
Michal Vasko7fbc8162018-09-17 10:35:16 +02004045
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004046 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004047
4048 /* get value */
Michal Vasko12ef5362022-09-16 15:13:58 +02004049 LY_CHECK_GOTO(ret = get_argument(ctx, Y_STR_ARG, NULL, &word, &buf, &word_len), cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01004050 CHECK_NONEMPTY(ctx, word_len, "deviation");
Michal Vasko12ef5362022-09-16 15:13:58 +02004051 INSERT_WORD_GOTO(ctx, buf, dev->nodeid, word, word_len, ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004052
Michal Vasko12ef5362022-09-16 15:13:58 +02004053 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks, goto cleanup) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004054 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02004055 case LY_STMT_DESCRIPTION:
Michal Vasko12ef5362022-09-16 15:13:58 +02004056 LY_CHECK_GOTO(ret = parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004057 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004058 case LY_STMT_DEVIATE:
Michal Vasko12ef5362022-09-16 15:13:58 +02004059 LY_CHECK_GOTO(ret = parse_deviate(ctx, &dev->deviates), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004060 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004061 case LY_STMT_REFERENCE:
Michal Vasko12ef5362022-09-16 15:13:58 +02004062 LY_CHECK_GOTO(ret = parse_text_field(ctx, LY_STMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004063 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004064 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko12ef5362022-09-16 15:13:58 +02004065 LY_CHECK_GOTO(ret = parse_ext(ctx, word, word_len, LY_STMT_DEVIATION, 0, &dev->exts), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004066 break;
4067 default:
David Sedlákb3077192019-06-19 10:55:37 +02004068 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko12ef5362022-09-16 15:13:58 +02004069 ret = LY_EVALID;
4070 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004071 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004072 }
Michal Vasko12ef5362022-09-16 15:13:58 +02004073 LY_CHECK_GOTO(ret, cleanup);
4074
Radek Krejci6d6556c2018-11-08 09:37:45 +01004075checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004076 /* mandatory substatements */
4077 if (!dev->deviates) {
David Sedlákb3077192019-06-19 10:55:37 +02004078 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko12ef5362022-09-16 15:13:58 +02004079 ret = LY_EVALID;
4080 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004081 }
4082
Michal Vasko12ef5362022-09-16 15:13:58 +02004083cleanup:
4084 if (ret) {
Michal Vaskoc636ea42022-09-16 10:20:31 +02004085 lysp_deviation_free(&fctx, dev);
Michal Vasko12ef5362022-09-16 15:13:58 +02004086 LY_ARRAY_DECREMENT_FREE(*deviations);
4087 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004088 return ret;
4089}
4090
Michal Vaskoea5abea2018-09-18 13:10:54 +02004091/**
4092 * @brief Parse the feature statement.
4093 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004094 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004095 * @param[in,out] features Features to add to.
4096 *
4097 * @return LY_ERR values.
4098 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004099LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01004100parse_feature(struct lys_yang_parser_ctx *ctx, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004101{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004102 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004103 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004104 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004105 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004106 struct lysp_feature *feat;
4107
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004108 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004109
4110 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01004111 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02004112 INSERT_WORD_GOTO(ctx, buf, feat->name, word, word_len, ret, cleanup);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004113
aPieceka24a2252021-05-07 10:52:31 +02004114 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004115 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02004116 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01004117 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004118 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004119 case LY_STMT_IF_FEATURE:
Radek Krejcifc596f92021-02-26 22:40:26 +01004120 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004121 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004122 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01004123 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004124 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004125 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01004126 LY_CHECK_RET(parse_status(ctx, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004127 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004128 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01004129 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_FEATURE, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004130 break;
4131 default:
David Sedlákb3077192019-06-19 10:55:37 +02004132 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004133 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004134 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004135 }
Michal Vasko12ef5362022-09-16 15:13:58 +02004136
4137cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004138 return ret;
4139}
4140
Michal Vaskoea5abea2018-09-18 13:10:54 +02004141/**
4142 * @brief Parse the identity statement.
4143 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004144 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004145 * @param[in,out] identities Identities to add to.
4146 *
4147 * @return LY_ERR values.
4148 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004149LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01004150parse_identity(struct lys_yang_parser_ctx *ctx, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004151{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004152 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004153 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004154 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004155 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004156 struct lysp_ident *ident;
4157
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004158 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004159
4160 /* get value */
Radek Krejci33090f92020-12-17 20:12:46 +01004161 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02004162 INSERT_WORD_GOTO(ctx, buf, ident->name, word, word_len, ret, cleanup);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004163
aPieceka24a2252021-05-07 10:52:31 +02004164 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004165 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02004166 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01004167 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004168 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004169 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02004170 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejcifc596f92021-02-26 22:40:26 +01004171 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_IF_FEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004172 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004173 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01004174 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004175 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004176 case LY_STMT_STATUS:
Radek Krejci33090f92020-12-17 20:12:46 +01004177 LY_CHECK_RET(parse_status(ctx, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004178 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004179 case LY_STMT_BASE:
Michal Vasko8a67eff2021-12-07 14:04:47 +01004180 if (ident->bases && (PARSER_CUR_PMOD(ctx)->version < LYS_VERSION_1_1)) {
David Sedlákb3077192019-06-19 10:55:37 +02004181 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
Radek Krejci10113652018-11-14 16:56:50 +01004182 return LY_EVALID;
4183 }
Radek Krejcifc596f92021-02-26 22:40:26 +01004184 LY_CHECK_RET(parse_text_fields(ctx, LY_STMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004185 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004186 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01004187 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_IDENTITY, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004188 break;
4189 default:
David Sedlákb3077192019-06-19 10:55:37 +02004190 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004191 return LY_EVALID;
4192 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004193 }
Michal Vasko12ef5362022-09-16 15:13:58 +02004194
4195cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004196 return ret;
4197}
4198
Michal Vaskoea5abea2018-09-18 13:10:54 +02004199/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004200 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004201 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004202 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004203 * @param[in,out] mod Module to write to.
4204 *
4205 * @return LY_ERR values.
4206 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004207LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01004208parse_module(struct lys_yang_parser_ctx *ctx, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004209{
4210 LY_ERR ret = 0;
4211 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004212 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004213 enum ly_stmt kw, prev_kw = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004214 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Michal Vasko8dc31992021-02-22 10:30:47 +01004215 const struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004216
Michal Vaskoc3781c32020-10-06 14:04:08 +02004217 mod->is_submod = 0;
4218
4219 /* module name */
Radek Krejci33090f92020-12-17 20:12:46 +01004220 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02004221 INSERT_WORD_GOTO(ctx, buf, mod->mod->name, word, word_len, ret, cleanup);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004222
aPieceka24a2252021-05-07 10:52:31 +02004223 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks, return ret) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004224
Radek Krejcie3846472018-10-15 15:24:51 +02004225#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004226 if (mod_stmt > SECTION) {LOGVAL_PARSER(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
Radek Krejcie3846472018-10-15 15:24:51 +02004227
Michal Vasko7fbc8162018-09-17 10:35:16 +02004228 switch (kw) {
4229 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004230 case LY_STMT_NAMESPACE:
4231 case LY_STMT_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004232 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4233 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004234 case LY_STMT_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004235 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004236 break;
4237 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004238 case LY_STMT_INCLUDE:
4239 case LY_STMT_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004240 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004241 break;
4242 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004243 case LY_STMT_ORGANIZATION:
4244 case LY_STMT_CONTACT:
4245 case LY_STMT_DESCRIPTION:
4246 case LY_STMT_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004247 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004248 break;
4249
4250 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004251 case LY_STMT_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004252 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004253 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004254 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004255 case LY_STMT_ANYDATA:
4256 case LY_STMT_ANYXML:
4257 case LY_STMT_AUGMENT:
4258 case LY_STMT_CHOICE:
4259 case LY_STMT_CONTAINER:
4260 case LY_STMT_DEVIATION:
4261 case LY_STMT_EXTENSION:
4262 case LY_STMT_FEATURE:
4263 case LY_STMT_GROUPING:
4264 case LY_STMT_IDENTITY:
4265 case LY_STMT_LEAF:
4266 case LY_STMT_LEAF_LIST:
4267 case LY_STMT_LIST:
4268 case LY_STMT_NOTIFICATION:
4269 case LY_STMT_RPC:
4270 case LY_STMT_TYPEDEF:
4271 case LY_STMT_USES:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004272 mod_stmt = Y_MOD_BODY;
4273 break;
Michal Vasko59a24f62021-12-14 11:18:32 +01004274 case LY_STMT_EXTENSION_INSTANCE:
4275 /* no place in the statement order defined */
4276 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004277 default:
4278 /* error handled in the next switch */
4279 break;
4280 }
Radek Krejcie3846472018-10-15 15:24:51 +02004281#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004282
Radek Krejcie3846472018-10-15 15:24:51 +02004283 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004284 switch (kw) {
4285 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004286 case LY_STMT_YANG_VERSION:
Radek Krejci33090f92020-12-17 20:12:46 +01004287 LY_CHECK_RET(parse_yangversion(ctx, &mod->version, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004288 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004289 case LY_STMT_NAMESPACE:
Radek Krejcifc596f92021-02-26 22:40:26 +01004290 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_NAMESPACE, 0, &mod->mod->ns, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004291 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004292 case LY_STMT_PREFIX:
Radek Krejcifc596f92021-02-26 22:40:26 +01004293 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_PREFIX, 0, &mod->mod->prefix, Y_IDENTIF_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004294 break;
4295
4296 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004297 case LY_STMT_INCLUDE:
Radek Krejci33090f92020-12-17 20:12:46 +01004298 LY_CHECK_RET(parse_include(ctx, mod->mod->name, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004299 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004300 case LY_STMT_IMPORT:
Radek Krejci33090f92020-12-17 20:12:46 +01004301 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004302 break;
4303
4304 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004305 case LY_STMT_ORGANIZATION:
Radek Krejcifc596f92021-02-26 22:40:26 +01004306 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_ORGANIZATION, 0, &mod->mod->org, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004307 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004308 case LY_STMT_CONTACT:
Radek Krejcifc596f92021-02-26 22:40:26 +01004309 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_CONTACT, 0, &mod->mod->contact, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004310 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004311 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01004312 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &mod->mod->dsc, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004313 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004314 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01004315 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &mod->mod->ref, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004316 break;
4317
4318 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004319 case LY_STMT_REVISION:
Radek Krejci33090f92020-12-17 20:12:46 +01004320 LY_CHECK_RET(parse_revision(ctx, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004321 break;
4322
4323 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004324 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02004325 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci0f969882020-08-21 16:56:47 +02004326 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02004327 case LY_STMT_ANYXML:
Radek Krejci33090f92020-12-17 20:12:46 +01004328 LY_CHECK_RET(parse_any(ctx, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004329 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004330 case LY_STMT_CHOICE:
Radek Krejci33090f92020-12-17 20:12:46 +01004331 LY_CHECK_RET(parse_choice(ctx, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004332 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004333 case LY_STMT_CONTAINER:
Radek Krejci33090f92020-12-17 20:12:46 +01004334 LY_CHECK_RET(parse_container(ctx, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004335 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004336 case LY_STMT_LEAF:
Radek Krejci33090f92020-12-17 20:12:46 +01004337 LY_CHECK_RET(parse_leaf(ctx, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004338 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004339 case LY_STMT_LEAF_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01004340 LY_CHECK_RET(parse_leaflist(ctx, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004341 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004342 case LY_STMT_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01004343 LY_CHECK_RET(parse_list(ctx, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004344 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004345 case LY_STMT_USES:
Radek Krejci33090f92020-12-17 20:12:46 +01004346 LY_CHECK_RET(parse_uses(ctx, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004347 break;
4348
Radek Krejcid6b76452019-09-03 17:03:03 +02004349 case LY_STMT_AUGMENT:
Radek Krejci33090f92020-12-17 20:12:46 +01004350 LY_CHECK_RET(parse_augment(ctx, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004351 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004352 case LY_STMT_DEVIATION:
Radek Krejci33090f92020-12-17 20:12:46 +01004353 LY_CHECK_RET(parse_deviation(ctx, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004354 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004355 case LY_STMT_EXTENSION:
Radek Krejci33090f92020-12-17 20:12:46 +01004356 LY_CHECK_RET(parse_extension(ctx, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004357 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004358 case LY_STMT_FEATURE:
Radek Krejci33090f92020-12-17 20:12:46 +01004359 LY_CHECK_RET(parse_feature(ctx, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004360 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004361 case LY_STMT_GROUPING:
Radek Krejci33090f92020-12-17 20:12:46 +01004362 LY_CHECK_RET(parse_grouping(ctx, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004363 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004364 case LY_STMT_IDENTITY:
Radek Krejci33090f92020-12-17 20:12:46 +01004365 LY_CHECK_RET(parse_identity(ctx, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004366 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004367 case LY_STMT_NOTIFICATION:
Radek Krejci33090f92020-12-17 20:12:46 +01004368 LY_CHECK_RET(parse_notif(ctx, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004369 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004370 case LY_STMT_RPC:
Radek Krejci33090f92020-12-17 20:12:46 +01004371 LY_CHECK_RET(parse_action(ctx, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004372 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004373 case LY_STMT_TYPEDEF:
Radek Krejci33090f92020-12-17 20:12:46 +01004374 LY_CHECK_RET(parse_typedef(ctx, NULL, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004375 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004376 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01004377 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_MODULE, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004378 break;
4379
4380 default:
David Sedlákb3077192019-06-19 10:55:37 +02004381 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004382 return LY_EVALID;
4383 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004384 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004385 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004386
Radek Krejci6d6556c2018-11-08 09:37:45 +01004387checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004388 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004389 if (!mod->mod->ns) {
David Sedlákb3077192019-06-19 10:55:37 +02004390 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004391 return LY_EVALID;
4392 } else if (!mod->mod->prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02004393 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004394 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004395 }
4396
Radek Krejcie9e987e2018-10-31 12:50:27 +01004397 /* submodules share the namespace with the module names, so there must not be
4398 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01004399 dup = ly_ctx_get_submodule_latest(PARSER_CTX(ctx), mod->mod->name);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004400 if (dup) {
Radek Krejci854e1552020-12-21 15:05:23 +01004401 LOGVAL_PARSER(ctx, LY_VCODE_NAME2_COL, "module", "submodule", mod->mod->name);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004402 return LY_EVALID;
4403 }
4404
Michal Vasko12ef5362022-09-16 15:13:58 +02004405cleanup:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004406 return ret;
4407}
4408
4409/**
4410 * @brief Parse submodule substatements.
4411 *
4412 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004413 * @param[out] submod Parsed submodule structure.
4414 *
4415 * @return LY_ERR values.
4416 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004417LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01004418parse_submodule(struct lys_yang_parser_ctx *ctx, struct lysp_submodule *submod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004419{
4420 LY_ERR ret = 0;
4421 char *buf, *word;
4422 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004423 enum ly_stmt kw, prev_kw = 0;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004424 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Michal Vasko8dc31992021-02-22 10:30:47 +01004425 const struct lysp_submodule *dup;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004426
Michal Vaskoc3781c32020-10-06 14:04:08 +02004427 submod->is_submod = 1;
4428
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004429 /* submodule name */
Radek Krejci33090f92020-12-17 20:12:46 +01004430 LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko12ef5362022-09-16 15:13:58 +02004431 INSERT_WORD_GOTO(ctx, buf, submod->name, word, word_len, ret, cleanup);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004432
aPieceka24a2252021-05-07 10:52:31 +02004433 YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, goto checks, return ret) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004434
4435#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004436 if (mod_stmt > SECTION) {LOGVAL_PARSER(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004437
4438 switch (kw) {
4439 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004440 case LY_STMT_BELONGS_TO:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004441 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4442 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004443 case LY_STMT_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004444 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4445 break;
4446 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004447 case LY_STMT_INCLUDE:
4448 case LY_STMT_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004449 CHECK_ORDER(Y_MOD_LINKAGE);
4450 break;
4451 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004452 case LY_STMT_ORGANIZATION:
4453 case LY_STMT_CONTACT:
4454 case LY_STMT_DESCRIPTION:
4455 case LY_STMT_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004456 CHECK_ORDER(Y_MOD_META);
4457 break;
4458
4459 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004460 case LY_STMT_REVISION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004461 CHECK_ORDER(Y_MOD_REVISION);
4462 break;
4463 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004464 case LY_STMT_ANYDATA:
4465 case LY_STMT_ANYXML:
4466 case LY_STMT_AUGMENT:
4467 case LY_STMT_CHOICE:
4468 case LY_STMT_CONTAINER:
4469 case LY_STMT_DEVIATION:
4470 case LY_STMT_EXTENSION:
4471 case LY_STMT_FEATURE:
4472 case LY_STMT_GROUPING:
4473 case LY_STMT_IDENTITY:
4474 case LY_STMT_LEAF:
4475 case LY_STMT_LEAF_LIST:
4476 case LY_STMT_LIST:
4477 case LY_STMT_NOTIFICATION:
4478 case LY_STMT_RPC:
4479 case LY_STMT_TYPEDEF:
4480 case LY_STMT_USES:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004481 mod_stmt = Y_MOD_BODY;
4482 break;
Michal Vasko59a24f62021-12-14 11:18:32 +01004483 case LY_STMT_EXTENSION_INSTANCE:
4484 /* no place in the statement order defined */
4485 break;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004486 default:
4487 /* error handled in the next switch */
4488 break;
4489 }
4490#undef CHECK_ORDER
4491
4492 prev_kw = kw;
4493 switch (kw) {
4494 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004495 case LY_STMT_YANG_VERSION:
Radek Krejci33090f92020-12-17 20:12:46 +01004496 LY_CHECK_RET(parse_yangversion(ctx, &submod->version, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004497 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004498 case LY_STMT_BELONGS_TO:
Radek Krejci33090f92020-12-17 20:12:46 +01004499 LY_CHECK_RET(parse_belongsto(ctx, &submod->prefix, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004500 break;
4501
4502 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004503 case LY_STMT_INCLUDE:
Radek Krejcieeee95c2021-01-19 10:57:22 +01004504 if (submod->version == LYS_VERSION_1_1) {
4505 LOGWRN(PARSER_CTX(ctx), "YANG version 1.1 expects all includes in main module, includes in submodules (%s) are not necessary.",
4506 submod->name);
4507 }
Radek Krejci33090f92020-12-17 20:12:46 +01004508 LY_CHECK_RET(parse_include(ctx, submod->name, &submod->includes));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004509 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004510 case LY_STMT_IMPORT:
Radek Krejci33090f92020-12-17 20:12:46 +01004511 LY_CHECK_RET(parse_import(ctx, submod->prefix, &submod->imports));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004512 break;
4513
4514 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004515 case LY_STMT_ORGANIZATION:
Radek Krejcifc596f92021-02-26 22:40:26 +01004516 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004517 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004518 case LY_STMT_CONTACT:
Radek Krejcifc596f92021-02-26 22:40:26 +01004519 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004520 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004521 case LY_STMT_DESCRIPTION:
Radek Krejcifc596f92021-02-26 22:40:26 +01004522 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004523 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004524 case LY_STMT_REFERENCE:
Radek Krejcifc596f92021-02-26 22:40:26 +01004525 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004526 break;
4527
4528 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004529 case LY_STMT_REVISION:
Radek Krejci33090f92020-12-17 20:12:46 +01004530 LY_CHECK_RET(parse_revision(ctx, &submod->revs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004531 break;
4532
4533 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004534 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02004535 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
Radek Krejci0f969882020-08-21 16:56:47 +02004536 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02004537 case LY_STMT_ANYXML:
Radek Krejci33090f92020-12-17 20:12:46 +01004538 LY_CHECK_RET(parse_any(ctx, kw, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004539 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004540 case LY_STMT_CHOICE:
Radek Krejci33090f92020-12-17 20:12:46 +01004541 LY_CHECK_RET(parse_choice(ctx, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004542 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004543 case LY_STMT_CONTAINER:
Radek Krejci33090f92020-12-17 20:12:46 +01004544 LY_CHECK_RET(parse_container(ctx, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004545 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004546 case LY_STMT_LEAF:
Radek Krejci33090f92020-12-17 20:12:46 +01004547 LY_CHECK_RET(parse_leaf(ctx, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004548 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004549 case LY_STMT_LEAF_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01004550 LY_CHECK_RET(parse_leaflist(ctx, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004551 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004552 case LY_STMT_LIST:
Radek Krejci33090f92020-12-17 20:12:46 +01004553 LY_CHECK_RET(parse_list(ctx, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004554 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004555 case LY_STMT_USES:
Radek Krejci33090f92020-12-17 20:12:46 +01004556 LY_CHECK_RET(parse_uses(ctx, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004557 break;
4558
Radek Krejcid6b76452019-09-03 17:03:03 +02004559 case LY_STMT_AUGMENT:
Radek Krejci33090f92020-12-17 20:12:46 +01004560 LY_CHECK_RET(parse_augment(ctx, NULL, &submod->augments));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004561 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004562 case LY_STMT_DEVIATION:
Radek Krejci33090f92020-12-17 20:12:46 +01004563 LY_CHECK_RET(parse_deviation(ctx, &submod->deviations));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004564 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004565 case LY_STMT_EXTENSION:
Radek Krejci33090f92020-12-17 20:12:46 +01004566 LY_CHECK_RET(parse_extension(ctx, &submod->extensions));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004567 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004568 case LY_STMT_FEATURE:
Radek Krejci33090f92020-12-17 20:12:46 +01004569 LY_CHECK_RET(parse_feature(ctx, &submod->features));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004570 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004571 case LY_STMT_GROUPING:
Radek Krejci33090f92020-12-17 20:12:46 +01004572 LY_CHECK_RET(parse_grouping(ctx, NULL, &submod->groupings));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004573 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004574 case LY_STMT_IDENTITY:
Radek Krejci33090f92020-12-17 20:12:46 +01004575 LY_CHECK_RET(parse_identity(ctx, &submod->identities));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004576 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004577 case LY_STMT_NOTIFICATION:
Radek Krejci33090f92020-12-17 20:12:46 +01004578 LY_CHECK_RET(parse_notif(ctx, NULL, &submod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004579 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004580 case LY_STMT_RPC:
Radek Krejci33090f92020-12-17 20:12:46 +01004581 LY_CHECK_RET(parse_action(ctx, NULL, &submod->rpcs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004582 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004583 case LY_STMT_TYPEDEF:
Radek Krejci33090f92020-12-17 20:12:46 +01004584 LY_CHECK_RET(parse_typedef(ctx, NULL, &submod->typedefs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004585 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004586 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01004587 LY_CHECK_RET(parse_ext(ctx, word, word_len, LY_STMT_SUBMODULE, 0, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004588 break;
4589
4590 default:
David Sedlákb3077192019-06-19 10:55:37 +02004591 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004592 return LY_EVALID;
4593 }
4594 }
4595 LY_CHECK_RET(ret);
4596
4597checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004598 /* mandatory substatements */
Michal Vaskoc3781c32020-10-06 14:04:08 +02004599 if (!submod->prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02004600 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004601 return LY_EVALID;
4602 }
4603
4604 /* submodules share the namespace with the module names, so there must not be
4605 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01004606 dup = ly_ctx_get_submodule_latest(PARSER_CTX(ctx), submod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02004607 /* main modules may have different revisions */
4608 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01004609 LOGVAL_PARSER(ctx, LY_VCODE_NAME_COL, "submodules", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004610 return LY_EVALID;
4611 }
4612
Michal Vasko12ef5362022-09-16 15:13:58 +02004613cleanup:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004614 return ret;
4615}
4616
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004617/**
4618 * @brief Skip any redundant characters, namely whitespaces and comments.
4619 *
4620 * @param[in] ctx Yang parser context.
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004621 * @return LY_SUCCESS on success.
4622 * @return LY_EVALID on invalid comment.
4623 */
4624static LY_ERR
Radek Krejci33090f92020-12-17 20:12:46 +01004625skip_redundant_chars(struct lys_yang_parser_ctx *ctx)
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004626{
4627 /* read some trailing spaces, new lines, or comments */
Radek Krejci33090f92020-12-17 20:12:46 +01004628 while (ctx->in->current[0]) {
4629 if (!strncmp(ctx->in->current, "//", 2)) {
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004630 /* one-line comment */
Radek Krejci33090f92020-12-17 20:12:46 +01004631 ly_in_skip(ctx->in, 2);
4632 LY_CHECK_RET(skip_comment(ctx, 1));
4633 } else if (!strncmp(ctx->in->current, "/*", 2)) {
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004634 /* block comment */
Radek Krejci33090f92020-12-17 20:12:46 +01004635 ly_in_skip(ctx->in, 2);
4636 LY_CHECK_RET(skip_comment(ctx, 2));
4637 } else if (isspace(ctx->in->current[0])) {
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004638 /* whitespace */
Radek Krejcidd713ce2021-01-04 23:12:12 +01004639 if (ctx->in->current[0] == '\n') {
4640 LY_IN_NEW_LINE(ctx->in);
4641 }
Radek Krejci33090f92020-12-17 20:12:46 +01004642 ly_in_skip(ctx->in, 1);
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004643 } else {
4644 break;
4645 }
4646 }
4647
4648 return LY_SUCCESS;
4649}
4650
Radek Krejcid4557c62018-09-17 11:42:09 +02004651LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01004652yang_parse_submodule(struct lys_yang_parser_ctx **context, struct ly_ctx *ly_ctx, struct lys_parser_ctx *main_ctx,
Radek Krejci0f969882020-08-21 16:56:47 +02004653 struct ly_in *in, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004654{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004655 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004656 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004657 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004658 enum ly_stmt kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004659 struct lysp_submodule *mod_p = NULL;
Michal Vaskoc636ea42022-09-16 10:20:31 +02004660 struct lysf_ctx fctx = {.ctx = ly_ctx};
Michal Vasko7fbc8162018-09-17 10:35:16 +02004661
aPiecek56be92a2021-07-01 07:18:10 +02004662 assert(context && ly_ctx && main_ctx && in && submod);
4663
David Sedlák1b623122019-08-05 15:27:49 +02004664 /* create context */
4665 *context = calloc(1, sizeof **context);
4666 LY_CHECK_ERR_RET(!(*context), LOGMEM(ly_ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01004667 (*context)->format = LYS_IN_YANG;
Radek Krejci33090f92020-12-17 20:12:46 +01004668 (*context)->in = in;
aPiecek56be92a2021-07-01 07:18:10 +02004669 (*context)->main_ctx = main_ctx;
David Sedlák1b623122019-08-05 15:27:49 +02004670
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004671 mod_p = calloc(1, sizeof *mod_p);
4672 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ly_ctx); ret = LY_EMEM, cleanup);
Michal Vasko8a67eff2021-12-07 14:04:47 +01004673 mod_p->mod = PARSER_CUR_PMOD(main_ctx)->mod;
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004674 mod_p->parsing = 1;
Michal Vasko8a67eff2021-12-07 14:04:47 +01004675
4676 /* use main context parsed mods adding the current one */
4677 (*context)->parsed_mods = main_ctx->parsed_mods;
4678 ly_set_add((*context)->parsed_mods, mod_p, 1, NULL);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004679
Radek Krejciddace2c2021-01-08 11:30:56 +01004680 LOG_LOCINIT(NULL, NULL, NULL, in);
Radek Krejci2efc45b2020-12-22 16:25:44 +01004681
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004682 /* skip redundant but valid characters at the beginning */
Radek Krejci33090f92020-12-17 20:12:46 +01004683 ret = skip_redundant_chars(*context);
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004684 LY_CHECK_GOTO(ret, cleanup);
4685
Michal Vasko7fbc8162018-09-17 10:35:16 +02004686 /* "module"/"submodule" */
Radek Krejci33090f92020-12-17 20:12:46 +01004687 ret = get_keyword(*context, &kw, &word, &word_len);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004688 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004689
Radek Krejcid6b76452019-09-03 17:03:03 +02004690 if (kw == LY_STMT_MODULE) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004691 LOGERR(ly_ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004692 ret = LY_EINVAL;
4693 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02004694 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02004695 LOGVAL_PARSER(*context, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004696 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004697 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004698 }
4699
Michal Vasko7fbc8162018-09-17 10:35:16 +02004700 /* substatements */
Radek Krejci33090f92020-12-17 20:12:46 +01004701 ret = parse_submodule(*context, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004702 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004703
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004704 /* skip redundant but valid characters at the end */
Radek Krejci33090f92020-12-17 20:12:46 +01004705 ret = skip_redundant_chars(*context);
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004706 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko63f3d842020-07-08 10:10:14 +02004707 if (in->current[0]) {
4708 LOGVAL_PARSER(*context, LY_VCODE_TRAILING_SUBMOD, 15, in->current, strlen(in->current) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004709 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004710 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004711 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004712
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004713 mod_p->parsing = 0;
4714 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004715
Radek Krejcibbe09a92018-11-08 09:36:54 +01004716cleanup:
Radek Krejciddace2c2021-01-08 11:30:56 +01004717 LOG_LOCBACK(0, 0, 0, 1);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004718 if (ret) {
Michal Vaskoc636ea42022-09-16 10:20:31 +02004719 lysp_module_free(&fctx, (struct lysp_module *)mod_p);
Michal Vaskob36053d2020-03-26 15:49:30 +01004720 yang_parser_ctx_free(*context);
David Sedlák1b623122019-08-05 15:27:49 +02004721 *context = NULL;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004722 }
4723
4724 return ret;
4725}
4726
4727LY_ERR
aPiecekc3e26142021-06-22 14:25:49 +02004728yang_parse_module(struct lys_yang_parser_ctx **context, struct ly_in *in, struct lys_module *mod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004729{
4730 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004731 char *word;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004732 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004733 enum ly_stmt kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004734 struct lysp_module *mod_p = NULL;
Michal Vaskoc636ea42022-09-16 10:20:31 +02004735 struct lysf_ctx fctx = {.ctx = mod->ctx};
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004736
David Sedlák1b623122019-08-05 15:27:49 +02004737 /* create context */
4738 *context = calloc(1, sizeof **context);
4739 LY_CHECK_ERR_RET(!(*context), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01004740 (*context)->format = LYS_IN_YANG;
Michal Vasko8a67eff2021-12-07 14:04:47 +01004741 LY_CHECK_ERR_RET(ly_set_new(&(*context)->parsed_mods), free(*context); LOGMEM(mod->ctx), LY_EMEM);
Radek Krejci33090f92020-12-17 20:12:46 +01004742 (*context)->in = in;
aPiecek8d4e75d2021-06-24 14:47:06 +02004743 (*context)->main_ctx = (struct lys_parser_ctx *)(*context);
David Sedlák1b623122019-08-05 15:27:49 +02004744
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004745 mod_p = calloc(1, sizeof *mod_p);
4746 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
4747 mod_p->mod = mod;
Michal Vasko8a67eff2021-12-07 14:04:47 +01004748 ly_set_add((*context)->parsed_mods, mod_p, 1, NULL);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004749
Radek Krejciddace2c2021-01-08 11:30:56 +01004750 LOG_LOCINIT(NULL, NULL, NULL, in);
Radek Krejci2efc45b2020-12-22 16:25:44 +01004751
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004752 /* skip redundant but valid characters at the beginning */
Radek Krejci33090f92020-12-17 20:12:46 +01004753 ret = skip_redundant_chars(*context);
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004754 LY_CHECK_GOTO(ret, cleanup);
4755
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004756 /* "module"/"submodule" */
Radek Krejci33090f92020-12-17 20:12:46 +01004757 ret = get_keyword(*context, &kw, &word, &word_len);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004758 LY_CHECK_GOTO(ret, cleanup);
4759
Radek Krejcid6b76452019-09-03 17:03:03 +02004760 if (kw == LY_STMT_SUBMODULE) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004761 LOGERR(mod->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004762 ret = LY_EINVAL;
4763 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02004764 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02004765 LOGVAL_PARSER((*context), LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004766 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004767 goto cleanup;
4768 }
4769
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004770 /* substatements */
Radek Krejci33090f92020-12-17 20:12:46 +01004771 ret = parse_module(*context, mod_p);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004772 LY_CHECK_GOTO(ret, cleanup);
4773
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004774 /* skip redundant but valid characters at the end */
Radek Krejci33090f92020-12-17 20:12:46 +01004775 ret = skip_redundant_chars(*context);
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004776 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko63f3d842020-07-08 10:10:14 +02004777 if (in->current[0]) {
4778 LOGVAL_PARSER(*context, LY_VCODE_TRAILING_MOD, 15, in->current, strlen(in->current) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004779 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004780 goto cleanup;
4781 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004782
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004783 mod->parsed = mod_p;
4784
4785cleanup:
Radek Krejciddace2c2021-01-08 11:30:56 +01004786 LOG_LOCBACK(0, 0, 0, 1);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004787 if (ret) {
Michal Vaskoc636ea42022-09-16 10:20:31 +02004788 lysp_module_free(&fctx, mod_p);
Michal Vaskob36053d2020-03-26 15:49:30 +01004789 yang_parser_ctx_free(*context);
David Sedlák1b623122019-08-05 15:27:49 +02004790 *context = NULL;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004791 }
4792
Michal Vasko7fbc8162018-09-17 10:35:16 +02004793 return ret;
4794}