blob: 9df5183eb7a2902f0774f732cb3a7a5958ce73e8 [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 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
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"
33#include "tree_schema.h"
Radek Krejci70853c52018-10-15 14:46:16 +020034#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020035
Radek Krejciceaf2122019-01-02 15:03:26 +010036/**
37 * @brief Insert WORD into the libyang context's dictionary and store as TARGET.
38 * @param[in] CTX yang parser context to access libyang context.
39 * @param[in] BUF buffer in case the word is not a constant and can be inserted directly (zero-copy)
40 * @param[out] TARGET variable where to store the pointer to the inserted value.
41 * @param[in] WORD string to store.
42 * @param[in] LEN length of the string in WORD to store.
43 */
Radek Krejci011e4aa2020-09-04 15:22:31 +020044#define INSERT_WORD_RET(CTX, BUF, TARGET, WORD, LEN) \
Michal Vasko5d24f6c2020-10-13 13:49:06 +020045 if (BUF) {LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(CTX), WORD, &(TARGET)));}\
46 else {LY_CHECK_RET(lydict_insert(PARSER_CTX(CTX), LEN ? WORD : "", LEN, &(TARGET)));}
Radek Krejci44ceedc2018-10-02 15:54:31 +020047
Radek Krejciceaf2122019-01-02 15:03:26 +010048/**
Michal Vasko63f3d842020-07-08 10:10:14 +020049 * @brief Read from the IN structure COUNT items. Also updates the indent value in yang parser context
Radek Krejciceaf2122019-01-02 15:03:26 +010050 * @param[in] CTX yang parser context to update its indent value.
Michal Vasko63f3d842020-07-08 10:10:14 +020051 * @param[in,out] IN input structure
Radek Krejciceaf2122019-01-02 15:03:26 +010052 * @param[in] COUNT number of items for which the DATA pointer is supposed to move on.
53 */
Michal Vasko63f3d842020-07-08 10:10:14 +020054#define MOVE_INPUT(CTX, IN, COUNT) ly_in_skip(IN, COUNT);(CTX)->indent+=COUNT
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020055
Michal Vaskoea5abea2018-09-18 13:10:54 +020056/**
57 * @brief Loop through all substatements providing, return if there are none.
58 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020059 * @param[in] CTX yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +020060 * @param[in] IN Input structure to read from.
Michal Vaskoea5abea2018-09-18 13:10:54 +020061 * @param[out] KW YANG keyword read.
62 * @param[out] WORD Pointer to the keyword itself.
63 * @param[out] WORD_LEN Length of the keyword.
64 * @param[out] ERR Variable for error storing.
65 *
66 * @return In case there are no substatements or a fatal error encountered.
67 */
Michal Vasko63f3d842020-07-08 10:10:14 +020068#define YANG_READ_SUBSTMT_FOR(CTX, IN, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
69 LY_CHECK_RET(get_keyword(CTX, IN, &KW, &WORD, &WORD_LEN)); \
Radek Krejcid6b76452019-09-03 17:03:03 +020070 if (KW == LY_STMT_SYNTAX_SEMICOLON) { \
Radek Krejci6d6556c2018-11-08 09:37:45 +010071 CHECKGOTO; \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010072 return LY_SUCCESS; \
Michal Vasko7fbc8162018-09-17 10:35:16 +020073 } \
Radek Krejcid6b76452019-09-03 17:03:03 +020074 if (KW != LY_STMT_SYNTAX_LEFT_BRACE) { \
David Sedlákb3077192019-06-19 10:55:37 +020075 LOGVAL_PARSER(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020076 return LY_EVALID; \
77 } \
Michal Vasko63f3d842020-07-08 10:10:14 +020078 for (ERR = get_keyword(CTX, IN, &KW, &WORD, &WORD_LEN); \
Radek Krejcid6b76452019-09-03 17:03:03 +020079 !ERR && (KW != LY_STMT_SYNTAX_RIGHT_BRACE); \
Michal Vasko63f3d842020-07-08 10:10:14 +020080 ERR = get_keyword(CTX, IN, &KW, &WORD, &WORD_LEN))
Michal Vasko7fbc8162018-09-17 10:35:16 +020081
Michal Vasko63f3d842020-07-08 10:10:14 +020082LY_ERR parse_container(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent,
Radek Krejci0f969882020-08-21 16:56:47 +020083 struct lysp_node **siblings);
Michal Vasko63f3d842020-07-08 10:10:14 +020084LY_ERR parse_uses(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings);
85LY_ERR parse_choice(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings);
86LY_ERR parse_case(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings);
87LY_ERR parse_list(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings);
88LY_ERR parse_grouping(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +020089
Michal Vaskoea5abea2018-09-18 13:10:54 +020090/**
91 * @brief Add another character to dynamic buffer, a low-level function.
92 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020093 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +020094 *
Radek Krejci404251e2018-10-09 12:06:44 +020095 * @param[in] ctx libyang context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +020096 * @param[in,out] in Input structure.
Radek Krejci44ceedc2018-10-02 15:54:31 +020097 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +020098 * @param[in,out] buf Buffer to use, can be moved by realloc().
99 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200100 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200101 *
102 * @return LY_ERR values.
103 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200104LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200105buf_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 +0200106{
Radek Krejcif13b87b2020-12-01 22:02:17 +0100107#define BUF_STEP 16;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200108 if (*buf_len <= (*buf_used) + len) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100109 *buf_len += BUF_STEP;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200110 *buf = ly_realloc(*buf, *buf_len);
111 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
112 }
Radek Krejcic0917392019-04-10 13:04:04 +0200113 if (*buf_used) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200114 ly_in_read(in, &(*buf)[*buf_used], len);
Radek Krejcic0917392019-04-10 13:04:04 +0200115 } else {
Michal Vasko63f3d842020-07-08 10:10:14 +0200116 ly_in_read(in, *buf, len);
Radek Krejcic0917392019-04-10 13:04:04 +0200117 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200118
Radek Krejci44ceedc2018-10-02 15:54:31 +0200119 (*buf_used) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200120 return LY_SUCCESS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100121#undef BUF_STEP
Michal Vasko7fbc8162018-09-17 10:35:16 +0200122}
123
Michal Vaskoea5abea2018-09-18 13:10:54 +0200124/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200125 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
126 *
127 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200128 * @param[in,out] in Input structure.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200129 * @param[in] arg Type of the input string to select method of checking character validity.
130 * @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 +0200131 * 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 +0200132 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
133 * @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 +0200134 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200135 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
David Sedlák40bb13b2019-07-10 14:34:18 +0200136 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
137 * 0 - colon not yet found (no prefix)
138 * 1 - \p c is the colon character
139 * 2 - prefix already processed, now processing the identifier
Michal Vaskoea5abea2018-09-18 13:10:54 +0200140 *
141 * @return LY_ERR values.
142 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200143LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200144buf_store_char(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum yang_arg arg, char **word_p, size_t *word_len,
Radek Krejci857189e2020-09-01 13:26:36 +0200145 char **word_b, size_t *buf_len, ly_bool need_buf, uint8_t *prefix)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200146{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200147 uint32_t c;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200148 size_t len;
149
Radek Krejcif29b7c32019-04-09 16:17:49 +0200150 /* check valid combination of input paremeters - if need_buf specified, word_b must be provided */
151 assert(!need_buf || (need_buf && word_b));
152
Radek Krejci44ceedc2018-10-02 15:54:31 +0200153 /* get UTF8 code point (and number of bytes coding the character) */
Michal Vasko63f3d842020-07-08 10:10:14 +0200154 LY_CHECK_ERR_RET(ly_getutf8(&in->current, &c, &len),
Michal Vasko69730152020-10-09 16:30:07 +0200155 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, in->current[-len]), LY_EVALID);
Michal Vasko63f3d842020-07-08 10:10:14 +0200156 in->current -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200157 if (c == '\n') {
158 ctx->indent = 0;
159 } else {
160 /* note - even the multibyte character is count as 1 */
161 ++ctx->indent;
162 }
163
Radek Krejci44ceedc2018-10-02 15:54:31 +0200164 /* check character validity */
165 switch (arg) {
166 case Y_IDENTIF_ARG:
Michal Vaskob36053d2020-03-26 15:49:30 +0100167 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !(*word_len), NULL));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200168 break;
169 case Y_PREF_IDENTIF_ARG:
Michal Vaskob36053d2020-03-26 15:49:30 +0100170 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !(*word_len), prefix));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200171 break;
172 case Y_STR_ARG:
173 case Y_MAYBE_STR_ARG:
Michal Vaskob36053d2020-03-26 15:49:30 +0100174 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200175 break;
176 }
177
Michal Vasko7fbc8162018-09-17 10:35:16 +0200178 if (word_b && *word_b) {
179 /* add another character into buffer */
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200180 if (buf_add_char(PARSER_CTX(ctx), in, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200181 return LY_EMEM;
182 }
183
184 /* in case of realloc */
185 *word_p = *word_b;
Radek Krejcif29b7c32019-04-09 16:17:49 +0200186 } else if (word_b && need_buf) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200187 /* first time we need a buffer, copy everything read up to now */
188 if (*word_len) {
189 *word_b = malloc(*word_len);
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200190 LY_CHECK_ERR_RET(!*word_b, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200191 *buf_len = *word_len;
192 memcpy(*word_b, *word_p, *word_len);
193 }
194
195 /* add this new character into buffer */
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200196 if (buf_add_char(PARSER_CTX(ctx), in, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200197 return LY_EMEM;
198 }
199
200 /* in case of realloc */
201 *word_p = *word_b;
202 } else {
203 /* just remember the first character pointer */
204 if (!*word_p) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200205 *word_p = (char *)in->current;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200206 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200207 /* ... and update the word's length */
208 (*word_len) += len;
Michal Vasko63f3d842020-07-08 10:10:14 +0200209 ly_in_skip(in, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200210 }
211
212 return LY_SUCCESS;
213}
214
Michal Vaskoea5abea2018-09-18 13:10:54 +0200215/**
216 * @brief Skip YANG comment in data.
217 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200218 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200219 * @param[in,out] in Input structure.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200220 * @param[in] comment Type of the comment to process:
221 * 1 for a one-line comment,
222 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200223 * @return LY_ERR values.
224 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200225LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +0200226skip_comment(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint8_t comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200227{
Radek Krejcif13b87b2020-12-01 22:02:17 +0100228 /* internal statuses: */
229#define COMMENT_NO 0 /* comment ended */
230#define COMMENT_LINE 1 /* in line comment */
231#define COMMENT_BLOCK 2 /* in block comment */
232#define COMMENT_BLOCK_END 3 /* in block comment with last read character '*' */
233
Michal Vasko63f3d842020-07-08 10:10:14 +0200234 while (in->current[0] && comment) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200235 switch (comment) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100236 case COMMENT_LINE:
Michal Vasko63f3d842020-07-08 10:10:14 +0200237 if (in->current[0] == '\n') {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100238 comment = COMMENT_NO;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200239 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200240 }
241 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100242 case COMMENT_BLOCK:
Michal Vasko63f3d842020-07-08 10:10:14 +0200243 if (in->current[0] == '*') {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100244 comment = COMMENT_BLOCK_END;
Michal Vasko63f3d842020-07-08 10:10:14 +0200245 } else if (in->current[0] == '\n') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200246 ++ctx->line;
247 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200248 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100249 case COMMENT_BLOCK_END:
Michal Vasko63f3d842020-07-08 10:10:14 +0200250 if (in->current[0] == '/') {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100251 comment = COMMENT_NO;
Michal Vasko63f3d842020-07-08 10:10:14 +0200252 } else if (in->current[0] != '*') {
253 if (in->current[0] == '\n') {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200254 ++ctx->line;
255 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100256 comment = COMMENT_BLOCK;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200257 }
258 break;
259 default:
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200260 LOGINT_RET(PARSER_CTX(ctx));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200261 }
262
Michal Vasko63f3d842020-07-08 10:10:14 +0200263 if (in->current[0] == '\n') {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200264 ctx->indent = 0;
265 } else {
266 ++ctx->indent;
267 }
Michal Vasko63f3d842020-07-08 10:10:14 +0200268 ++in->current;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200269 }
270
Radek Krejcif13b87b2020-12-01 22:02:17 +0100271 if (!in->current[0] && (comment >= COMMENT_BLOCK)) {
David Sedlákb3077192019-06-19 10:55:37 +0200272 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Unexpected end-of-input, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200273 return LY_EVALID;
274 }
275
276 return LY_SUCCESS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100277
278#undef COMMENT_NO
279#undef COMMENT_LINE
280#undef COMMENT_BLOCK
281#undef COMMENT_BLOCK_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200282}
283
Michal Vaskoea5abea2018-09-18 13:10:54 +0200284/**
285 * @brief Read a quoted string from data.
286 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200287 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200288 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200289 * @param[in] arg Type of YANG keyword argument expected.
290 * @param[out] word_p Pointer to the read quoted string.
291 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
292 * set to NULL. Otherwise equal to \p word_p.
293 * @param[out] word_len Length of the read quoted string.
294 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
295 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
296 * indenation in the final quoted string.
297 *
298 * @return LY_ERR values.
299 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200300static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200301read_qstring(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum yang_arg arg, char **word_p, char **word_b,
Radek Krejci0f969882020-08-21 16:56:47 +0200302 size_t *word_len, size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200303{
Radek Krejcif13b87b2020-12-01 22:02:17 +0100304 /* string parsing status: */
305#define STRING_ENDED 0 /* string ended */
306#define STRING_SINGLE_QUOTED 1 /* string with ' */
307#define STRING_DOUBLE_QUOTED 2 /* string with " */
308#define STRING_DOUBLE_QUOTED_ESCAPED 3 /* string with " with last character \ */
309#define STRING_PAUSED_NEXTSTRING 4 /* string finished, now skipping whitespaces looking for + */
310#define STRING_PAUSED_CONTINUE 5 /* string continues after +, skipping whitespaces */
311
Radek Krejci1deb5be2020-08-26 16:43:36 +0200312 uint8_t string;
313 uint64_t block_indent = 0, current_indent = 0;
Radek Krejci857189e2020-09-01 13:26:36 +0200314 ly_bool need_buf = 0;
315 uint8_t prefix = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200316 const char *c;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200317 uint64_t trailing_ws = 0; /* current number of stored trailing whitespace characters */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200318
Michal Vasko63f3d842020-07-08 10:10:14 +0200319 if (in->current[0] == '\"') {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100320 string = STRING_DOUBLE_QUOTED;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200321 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200322 } else {
Michal Vasko63f3d842020-07-08 10:10:14 +0200323 assert(in->current[0] == '\'');
Radek Krejcif13b87b2020-12-01 22:02:17 +0100324 string = STRING_SINGLE_QUOTED;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200325 }
Michal Vasko63f3d842020-07-08 10:10:14 +0200326 MOVE_INPUT(ctx, in, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200327
Michal Vasko63f3d842020-07-08 10:10:14 +0200328 while (in->current[0] && string) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200329 switch (string) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100330 case STRING_SINGLE_QUOTED:
Michal Vasko63f3d842020-07-08 10:10:14 +0200331 switch (in->current[0]) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200332 case '\'':
333 /* string may be finished, but check for + */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100334 string = STRING_PAUSED_NEXTSTRING;
Michal Vasko63f3d842020-07-08 10:10:14 +0200335 MOVE_INPUT(ctx, in, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200336 break;
337 default:
338 /* check and store character */
Michal Vasko63f3d842020-07-08 10:10:14 +0200339 LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200340 break;
341 }
342 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100343 case STRING_DOUBLE_QUOTED:
Michal Vasko63f3d842020-07-08 10:10:14 +0200344 switch (in->current[0]) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200345 case '\"':
346 /* string may be finished, but check for + */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100347 string = STRING_PAUSED_NEXTSTRING;
Michal Vasko63f3d842020-07-08 10:10:14 +0200348 MOVE_INPUT(ctx, in, 1);
Radek Krejciff13cd12019-10-25 15:34:24 +0200349 trailing_ws = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200350 break;
351 case '\\':
352 /* special character following */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100353 string = STRING_DOUBLE_QUOTED_ESCAPED;
Radek Krejciff13cd12019-10-25 15:34:24 +0200354
355 /* the backslash sequence is substituted, so we will need a buffer to store the result */
356 need_buf = 1;
357
358 /* move forward to the escaped character */
Michal Vasko63f3d842020-07-08 10:10:14 +0200359 ++in->current;
Radek Krejciff13cd12019-10-25 15:34:24 +0200360
361 /* note that the trailing whitespaces are supposed to be trimmed before substitution of
362 * backslash-escaped characters (RFC 7950, 6.1.3), so we have to zero the trailing whitespaces counter */
363 trailing_ws = 0;
364
365 /* since the backslash-escaped character is handled as first non-whitespace character, stop eating indentation */
366 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200367 break;
368 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200369 if (current_indent < block_indent) {
370 ++current_indent;
Michal Vasko63f3d842020-07-08 10:10:14 +0200371 MOVE_INPUT(ctx, in, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200372 } else {
Michal Vasko90edde42019-11-25 15:25:07 +0100373 /* check and store whitespace character */
Michal Vasko63f3d842020-07-08 10:10:14 +0200374 LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko90edde42019-11-25 15:25:07 +0100375 trailing_ws++;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200376 }
377 break;
378 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200379 if (current_indent < block_indent) {
380 assert(need_buf);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100381 current_indent += Y_TAB_SPACES;
382 ctx->indent += Y_TAB_SPACES;
Michal Vaskod989ba02020-08-24 10:59:24 +0200383 for ( ; current_indent > block_indent; --current_indent, --ctx->indent) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200384 /* store leftover spaces from the tab */
Michal Vasko63f3d842020-07-08 10:10:14 +0200385 c = in->current;
386 in->current = " ";
387 LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
388 in->current = c;
Michal Vasko90edde42019-11-25 15:25:07 +0100389 trailing_ws++;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200390 }
Michal Vasko63f3d842020-07-08 10:10:14 +0200391 ++in->current;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200392 } else {
Michal Vasko90edde42019-11-25 15:25:07 +0100393 /* check and store whitespace character */
Michal Vasko63f3d842020-07-08 10:10:14 +0200394 LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko90edde42019-11-25 15:25:07 +0100395 trailing_ws++;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200396 /* additional characters for indentation - only 1 was count in buf_store_char */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100397 ctx->indent += Y_TAB_SPACES - 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200398 }
399 break;
400 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200401 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200402 /* we will be removing the indents so we need our own buffer */
403 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200404
405 /* remove trailing tabs and spaces */
Radek Krejciff13cd12019-10-25 15:34:24 +0200406 (*word_len) = *word_len - trailing_ws;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200407
Radek Krejciff13cd12019-10-25 15:34:24 +0200408 /* restart indentation */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200409 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200410 }
411
412 /* check and store character */
Michal Vasko63f3d842020-07-08 10:10:14 +0200413 LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200414
415 /* maintain line number */
416 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200417
418 /* reset context indentation counter for possible string after this one */
419 ctx->indent = 0;
Radek Krejciff13cd12019-10-25 15:34:24 +0200420 trailing_ws = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200421 break;
422 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200423 /* first non-whitespace character, stop eating indentation */
424 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200425
426 /* check and store character */
Michal Vasko63f3d842020-07-08 10:10:14 +0200427 LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Radek Krejciff13cd12019-10-25 15:34:24 +0200428 trailing_ws = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200429 break;
430 }
431 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100432 case STRING_DOUBLE_QUOTED_ESCAPED:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200433 /* string encoded characters */
Michal Vasko63f3d842020-07-08 10:10:14 +0200434 c = in->current;
435 switch (in->current[0]) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200436 case 'n':
Michal Vasko63f3d842020-07-08 10:10:14 +0200437 in->current = "\n";
Michal Vasko7fbc8162018-09-17 10:35:16 +0200438 break;
439 case 't':
Michal Vasko63f3d842020-07-08 10:10:14 +0200440 in->current = "\t";
Michal Vasko7fbc8162018-09-17 10:35:16 +0200441 break;
442 case '\"':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200443 case '\\':
Michal Vasko63f3d842020-07-08 10:10:14 +0200444 /* ok as is */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200445 break;
446 default:
Michal Vasko63f3d842020-07-08 10:10:14 +0200447 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.",
Michal Vasko69730152020-10-09 16:30:07 +0200448 in->current[0]);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200449 return LY_EVALID;
450 }
451
452 /* check and store character */
Michal Vasko63f3d842020-07-08 10:10:14 +0200453 LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200454
Radek Krejcif13b87b2020-12-01 22:02:17 +0100455 string = STRING_DOUBLE_QUOTED;
Michal Vasko63f3d842020-07-08 10:10:14 +0200456 in->current = c + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200457 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100458 case STRING_PAUSED_NEXTSTRING:
Michal Vasko63f3d842020-07-08 10:10:14 +0200459 switch (in->current[0]) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200460 case '+':
461 /* string continues */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100462 string = STRING_PAUSED_CONTINUE;
Radek Krejciefd22f62018-09-27 11:47:58 +0200463 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200464 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200465 case '\n':
466 ++ctx->line;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100467 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200468 case ' ':
469 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200470 /* just skip */
471 break;
472 default:
473 /* string is finished */
474 goto string_end;
475 }
Michal Vasko63f3d842020-07-08 10:10:14 +0200476 MOVE_INPUT(ctx, in, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200477 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100478 case STRING_PAUSED_CONTINUE:
Michal Vasko63f3d842020-07-08 10:10:14 +0200479 switch (in->current[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200480 case '\n':
481 ++ctx->line;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100482 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200483 case ' ':
484 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200485 /* skip */
486 break;
487 case '\'':
Radek Krejcif13b87b2020-12-01 22:02:17 +0100488 string = STRING_SINGLE_QUOTED;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200489 break;
490 case '\"':
Radek Krejcif13b87b2020-12-01 22:02:17 +0100491 string = STRING_DOUBLE_QUOTED;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200492 break;
493 default:
494 /* it must be quoted again */
David Sedlákb3077192019-06-19 10:55:37 +0200495 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200496 return LY_EVALID;
497 }
Michal Vasko63f3d842020-07-08 10:10:14 +0200498 MOVE_INPUT(ctx, in, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200499 break;
500 default:
501 return LY_EINT;
502 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200503 }
504
505string_end:
Michal Vasko69730152020-10-09 16:30:07 +0200506 if ((arg <= Y_PREF_IDENTIF_ARG) && !(*word_len)) {
Radek Krejci4e199f52019-05-28 09:09:28 +0200507 /* empty identifier */
David Sedlákb3077192019-06-19 10:55:37 +0200508 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Statement argument is required.");
Radek Krejci4e199f52019-05-28 09:09:28 +0200509 return LY_EVALID;
510 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200511 return LY_SUCCESS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100512
513#undef STRING_ENDED
514#undef STRING_SINGLE_QUOTED
515#undef STRING_DOUBLE_QUOTED
516#undef STRING_DOUBLE_QUOTED_ESCAPED
517#undef STRING_PAUSED_NEXTSTRING
518#undef STRING_PAUSED_CONTINUE
Michal Vasko7fbc8162018-09-17 10:35:16 +0200519}
520
Michal Vaskoea5abea2018-09-18 13:10:54 +0200521/**
522 * @brief Get another YANG string from the raw data.
523 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200524 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200525 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200526 * @param[in] arg Type of YANG keyword argument expected.
Radek Krejcid3ca0632019-04-16 16:54:54 +0200527 * @param[out] flags optional output argument to get flag of the argument's quoting (LYS_*QOUTED - see [schema node flags](@ref snodeflags))
Michal Vasko2ca70f52018-09-27 11:04:51 +0200528 * @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 +0200529 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
530 * set to NULL. Otherwise equal to \p word_p.
531 * @param[out] word_len Length of the read string.
532 *
533 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200534 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200535LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200536get_argument(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum yang_arg arg, uint16_t *flags, char **word_p,
Radek Krejci0f969882020-08-21 16:56:47 +0200537 char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200538{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200539 size_t buf_len = 0;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200540 uint8_t prefix = 0;
Michal Vasko69730152020-10-09 16:30:07 +0200541
Michal Vasko7fbc8162018-09-17 10:35:16 +0200542 /* word buffer - dynamically allocated */
543 *word_b = NULL;
544
545 /* word pointer - just a pointer to data */
546 *word_p = NULL;
547
548 *word_len = 0;
Michal Vasko63f3d842020-07-08 10:10:14 +0200549 while (in->current[0]) {
550 switch (in->current[0]) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200551 case '\'':
552 case '\"':
553 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200554 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
Michal Vasko63f3d842020-07-08 10:10:14 +0200555 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, in->current,
Michal Vasko69730152020-10-09 16:30:07 +0200556 "unquoted string character, optsep, semicolon or opening brace");
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200557 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200558 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200559 if (flags) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200560 (*flags) |= in->current[0] == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200561 }
Michal Vasko63f3d842020-07-08 10:10:14 +0200562 LY_CHECK_RET(read_qstring(ctx, in, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200563 goto str_end;
564 case '/':
Michal Vasko63f3d842020-07-08 10:10:14 +0200565 if (in->current[1] == '/') {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200566 /* one-line comment */
Michal Vasko63f3d842020-07-08 10:10:14 +0200567 MOVE_INPUT(ctx, in, 2);
568 LY_CHECK_RET(skip_comment(ctx, in, 1));
569 } else if (in->current[1] == '*') {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200570 /* block comment */
Michal Vasko63f3d842020-07-08 10:10:14 +0200571 MOVE_INPUT(ctx, in, 2);
572 LY_CHECK_RET(skip_comment(ctx, in, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200573 } else {
574 /* not a comment after all */
Michal Vasko63f3d842020-07-08 10:10:14 +0200575 LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, &buf_len, 0, &prefix));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200576 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200577 break;
578 case ' ':
579 if (*word_len) {
580 /* word is finished */
581 goto str_end;
582 }
Michal Vasko63f3d842020-07-08 10:10:14 +0200583 MOVE_INPUT(ctx, in, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200584 break;
585 case '\t':
586 if (*word_len) {
587 /* word is finished */
588 goto str_end;
589 }
590 /* tabs count for 8 spaces */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100591 ctx->indent += Y_TAB_SPACES;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200592
Michal Vasko63f3d842020-07-08 10:10:14 +0200593 ++in->current;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200594 break;
595 case '\n':
596 if (*word_len) {
597 /* word is finished */
598 goto str_end;
599 }
600 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200601 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200602
603 /* track line numbers */
604 ++ctx->line;
605
Michal Vasko63f3d842020-07-08 10:10:14 +0200606 ++in->current;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200607 break;
608 case ';':
609 case '{':
610 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
611 /* word is finished */
612 goto str_end;
613 }
614
Michal Vasko63f3d842020-07-08 10:10:14 +0200615 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, in->current, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200616 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200617 case '}':
618 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
Michal Vasko63f3d842020-07-08 10:10:14 +0200619 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, in->current,
Michal Vasko69730152020-10-09 16:30:07 +0200620 "unquoted string character, optsep, semicolon or opening brace");
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200621 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200622 default:
Michal Vasko63f3d842020-07-08 10:10:14 +0200623 LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, &buf_len, 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200624 break;
625 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200626 }
627
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200628 /* unexpected end of loop */
David Sedlákb3077192019-06-19 10:55:37 +0200629 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200630 return LY_EVALID;
631
Michal Vasko7fbc8162018-09-17 10:35:16 +0200632str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200633 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200634 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200635 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200636 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200637 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200638 *word_p = *word_b;
639 }
640
641 return LY_SUCCESS;
642}
643
Michal Vaskoea5abea2018-09-18 13:10:54 +0200644/**
645 * @brief Get another YANG keyword from the raw data.
646 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200647 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200648 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200649 * @param[out] kw YANG keyword read.
650 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
651 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
652 *
653 * @return LY_ERR values.
654 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200655LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200656get_keyword(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt *kw, char **word_p, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200657{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200658 uint8_t prefix;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200659 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200660 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200661
662 if (word_p) {
663 *word_p = NULL;
664 *word_len = 0;
665 }
666
667 /* first skip "optsep", comments */
Michal Vasko63f3d842020-07-08 10:10:14 +0200668 while (in->current[0]) {
669 switch (in->current[0]) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200670 case '/':
Michal Vasko63f3d842020-07-08 10:10:14 +0200671 if (in->current[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200672 /* one-line comment */
Michal Vasko63f3d842020-07-08 10:10:14 +0200673 MOVE_INPUT(ctx, in, 2);
674 LY_CHECK_RET(skip_comment(ctx, in, 1));
675 } else if (in->current[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200676 /* block comment */
Michal Vasko63f3d842020-07-08 10:10:14 +0200677 MOVE_INPUT(ctx, in, 2);
678 LY_CHECK_RET(skip_comment(ctx, in, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200679 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200680 /* error - not a comment after all, keyword cannot start with slash */
David Sedlákb3077192019-06-19 10:55:37 +0200681 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
Radek Krejcidcc7b322018-10-11 14:24:02 +0200682 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200683 }
Radek Krejci13028282019-06-11 14:56:48 +0200684 continue;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200685 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200686 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200687 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200688 ctx->indent = 0;
689 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200690 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200691 /* skip whitespaces (optsep) */
692 ++ctx->indent;
693 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200694 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200695 /* skip whitespaces (optsep) */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100696 ctx->indent += Y_TAB_SPACES;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200697 break;
698 default:
699 /* either a keyword start or an invalid character */
700 goto keyword_start;
701 }
702
Michal Vasko63f3d842020-07-08 10:10:14 +0200703 ly_in_skip(in, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200704 }
705
706keyword_start:
Michal Vasko63f3d842020-07-08 10:10:14 +0200707 word_start = in->current;
708 *kw = lysp_match_kw(ctx, in);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200709
Michal Vasko69730152020-10-09 16:30:07 +0200710 if ((*kw == LY_STMT_SYNTAX_SEMICOLON) || (*kw == LY_STMT_SYNTAX_LEFT_BRACE) || (*kw == LY_STMT_SYNTAX_RIGHT_BRACE)) {
Radek Krejci626df482018-10-11 15:06:31 +0200711 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200712 }
713
Radek Krejcid6b76452019-09-03 17:03:03 +0200714 if (*kw != LY_STMT_NONE) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200715 /* make sure we have the whole keyword */
Michal Vasko63f3d842020-07-08 10:10:14 +0200716 switch (in->current[0]) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200717 case '\n':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200718 case '\t':
Radek Krejciabdd8062019-06-11 16:44:19 +0200719 case ' ':
720 /* mandatory "sep" is just checked, not eaten so nothing in the context is updated */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200721 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200722 case ':':
723 /* keyword is not actually a keyword, but prefix of an extension.
724 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
725 * and we will be checking the keyword (extension instance) itself */
726 prefix = 1;
Michal Vasko63f3d842020-07-08 10:10:14 +0200727 MOVE_INPUT(ctx, in, 1);
Radek Krejci156ccaf2018-10-15 15:49:17 +0200728 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200729 case '{':
730 /* allowed only for input and output statements which can be without arguments */
Michal Vasko69730152020-10-09 16:30:07 +0200731 if ((*kw == LY_STMT_INPUT) || (*kw == LY_STMT_OUTPUT)) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200732 break;
733 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100734 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200735 default:
Michal Vasko63f3d842020-07-08 10:10:14 +0200736 MOVE_INPUT(ctx, in, 1);
737 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(in->current - word_start), word_start,
Michal Vasko69730152020-10-09 16:30:07 +0200738 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200739 return LY_EVALID;
740 }
741 } else {
742 /* still can be an extension */
743 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200744extension:
Michal Vasko69730152020-10-09 16:30:07 +0200745 while (in->current[0] && (in->current[0] != ' ') && (in->current[0] != '\t') && (in->current[0] != '\n') &&
746 (in->current[0] != '{') && (in->current[0] != ';')) {
Radek Krejci1deb5be2020-08-26 16:43:36 +0200747 uint32_t c = 0;
748
Michal Vasko63f3d842020-07-08 10:10:14 +0200749 LY_CHECK_ERR_RET(ly_getutf8(&in->current, &c, &len),
Michal Vasko69730152020-10-09 16:30:07 +0200750 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, in->current[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200751 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200752 /* check character validity */
Michal Vasko63f3d842020-07-08 10:10:14 +0200753 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c,
Michal Vasko69730152020-10-09 16:30:07 +0200754 in->current - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200755 }
Michal Vasko63f3d842020-07-08 10:10:14 +0200756 if (!in->current[0]) {
David Sedlákb3077192019-06-19 10:55:37 +0200757 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200758 return LY_EVALID;
759 }
760
761 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200762 if (prefix != 2) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200763 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(in->current - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200764 return LY_EVALID;
765 }
766
Radek Krejcid6b76452019-09-03 17:03:03 +0200767 *kw = LY_STMT_EXTENSION_INSTANCE;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200768 }
Radek Krejci626df482018-10-11 15:06:31 +0200769success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200770 if (word_p) {
771 *word_p = (char *)word_start;
Michal Vasko63f3d842020-07-08 10:10:14 +0200772 *word_len = in->current - word_start;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200773 }
774
775 return LY_SUCCESS;
776}
777
Michal Vaskoea5abea2018-09-18 13:10:54 +0200778/**
779 * @brief Parse extension instance substatements.
780 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200781 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200782 * @param[in,out] in Input structure.
Radek Krejci335332a2019-09-05 13:03:35 +0200783 * @param[in] kw Statement keyword value matching @p word value.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200784 * @param[in] word Extension instance substatement name (keyword).
785 * @param[in] word_len Extension instance substatement name length.
786 * @param[in,out] child Children of this extension instance to add to.
787 *
788 * @return LY_ERR values.
789 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200790static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200791parse_ext_substmt(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt kw, char *word, size_t word_len,
Radek Krejci0f969882020-08-21 16:56:47 +0200792 struct lysp_stmt **child)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200793{
794 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100795 LY_ERR ret = LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200796 enum ly_stmt child_kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200797 struct lysp_stmt *stmt, *par_child;
798
799 stmt = calloc(1, sizeof *stmt);
800 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
801
Radek Krejcibb9b1982019-04-08 14:24:59 +0200802 /* insert into parent statements */
803 if (!*child) {
804 *child = stmt;
805 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +0200806 for (par_child = *child; par_child->next; par_child = par_child->next) {}
Radek Krejcibb9b1982019-04-08 14:24:59 +0200807 par_child->next = stmt;
808 }
809
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200810 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), word, word_len, &stmt->stmt));
Radek Krejci335332a2019-09-05 13:03:35 +0200811 stmt->kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200812
813 /* get optional argument */
Michal Vasko63f3d842020-07-08 10:10:14 +0200814 LY_CHECK_RET(get_argument(ctx, in, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200815
Radek Krejci0ae092d2018-09-20 16:43:19 +0200816 if (word) {
817 if (buf) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200818 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), word, &stmt->arg));
Radek Krejci0ae092d2018-09-20 16:43:19 +0200819 } else {
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200820 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), word, word_len, &stmt->arg));
Radek Krejci0ae092d2018-09-20 16:43:19 +0200821 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200822 }
823
Michal Vasko63f3d842020-07-08 10:10:14 +0200824 YANG_READ_SUBSTMT_FOR(ctx, in, child_kw, word, word_len, ret, ) {
825 LY_CHECK_RET(parse_ext_substmt(ctx, in, child_kw, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200826 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200827 return ret;
828}
829
Michal Vaskoea5abea2018-09-18 13:10:54 +0200830/**
831 * @brief Parse extension instance.
832 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200833 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200834 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200835 * @param[in] ext_name Extension instance substatement name (keyword).
836 * @param[in] ext_name_len Extension instance substatement name length.
837 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
838 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
839 * @param[in,out] exts Extension instances to add to.
840 *
841 * @return LY_ERR values.
842 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200843static LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +0200844parse_ext(struct lys_yang_parser_ctx *ctx, struct ly_in *in, const char *ext_name, size_t ext_name_len, LYEXT_SUBSTMT insubstmt,
Radek Krejci0f969882020-08-21 16:56:47 +0200845 LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200846{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100847 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200848 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200849 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200850 struct lysp_ext_instance *e;
Radek Krejcid6b76452019-09-03 17:03:03 +0200851 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200852
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200853 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200854
855 /* store name and insubstmt info */
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200856 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), ext_name, ext_name_len, &e->name));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200857 e->insubstmt = insubstmt;
858 e->insubstmt_index = insubstmt_index;
859
860 /* get optional argument */
Michal Vasko63f3d842020-07-08 10:10:14 +0200861 LY_CHECK_RET(get_argument(ctx, in, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200862
Radek Krejci0ae092d2018-09-20 16:43:19 +0200863 if (word) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200864 INSERT_WORD_RET(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200865 }
866
Michal Vaskod989ba02020-08-24 10:59:24 +0200867 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200868 LY_CHECK_RET(parse_ext_substmt(ctx, in, kw, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200869 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200870 return ret;
871}
872
Michal Vaskoea5abea2018-09-18 13:10:54 +0200873/**
874 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
875 * description, etc...
876 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200877 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200878 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200879 * @param[in] substmt Type of this substatement.
880 * @param[in] substmt_index Index of this substatement.
881 * @param[in,out] value Place to store the parsed value.
882 * @param[in] arg Type of the YANG keyword argument (of the value).
883 * @param[in,out] exts Extension instances to add to.
884 *
885 * @return LY_ERR values.
886 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200887static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200888parse_text_field(struct lys_yang_parser_ctx *ctx, struct ly_in *in, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Radek Krejci0f969882020-08-21 16:56:47 +0200889 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200890{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100891 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200892 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200893 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200894 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200895
896 if (*value) {
David Sedlákb3077192019-06-19 10:55:37 +0200897 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200898 return LY_EVALID;
899 }
900
901 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +0200902 LY_CHECK_RET(get_argument(ctx, in, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200903
904 /* store value and spend buf if allocated */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200905 INSERT_WORD_RET(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200906
Michal Vaskod989ba02020-08-24 10:59:24 +0200907 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200908 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200909 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +0200910 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200911 break;
912 default:
David Sedlákb3077192019-06-19 10:55:37 +0200913 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200914 return LY_EVALID;
915 }
916 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200917 return ret;
918}
919
Michal Vaskoea5abea2018-09-18 13:10:54 +0200920/**
921 * @brief Parse the yang-version statement.
922 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200923 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200924 * @param[in,out] in Input structure.
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100925 * @param[out] version Storage for the parsed information.
Michal Vasko63f3d842020-07-08 10:10:14 +0200926 * @param[in,out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200927 *
928 * @return LY_ERR values.
929 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200930static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200931parse_yangversion(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200932{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100933 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200934 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200935 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200936 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200937
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100938 if (*version) {
David Sedlákb3077192019-06-19 10:55:37 +0200939 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200940 return LY_EVALID;
941 }
942
943 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +0200944 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200945
Radek Krejci96e48da2020-09-04 13:18:06 +0200946 if ((word_len == 1) && !strncmp(word, "1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100947 *version = LYS_VERSION_1_0;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100948 } else if ((word_len == ly_strlen_const("1.1")) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100949 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200950 } else {
David Sedlákb3077192019-06-19 10:55:37 +0200951 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200952 free(buf);
953 return LY_EVALID;
954 }
955 free(buf);
956
Michal Vaskod989ba02020-08-24 10:59:24 +0200957 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200958 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200959 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +0200960 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200961 break;
962 default:
David Sedlákb3077192019-06-19 10:55:37 +0200963 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200964 return LY_EVALID;
965 }
966 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200967 return ret;
968}
969
Michal Vaskoea5abea2018-09-18 13:10:54 +0200970/**
971 * @brief Parse the belongs-to statement.
972 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200973 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +0200974 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200975 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
976 * @param[in,out] exts Extension instances to add to.
977 *
978 * @return LY_ERR values.
979 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200980static LY_ERR
Michal Vaskoc3781c32020-10-06 14:04:08 +0200981parse_belongsto(struct lys_yang_parser_ctx *ctx, struct ly_in *in, const char **prefix, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200982{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100983 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200984 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200985 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200986 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200987
Michal Vaskoc3781c32020-10-06 14:04:08 +0200988 if (*prefix) {
David Sedlákb3077192019-06-19 10:55:37 +0200989 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200990 return LY_EVALID;
991 }
992
Michal Vaskoc3781c32020-10-06 14:04:08 +0200993 /* get value, it must match the main module */
Michal Vasko63f3d842020-07-08 10:10:14 +0200994 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200995 if (ly_strncmp(ctx->parsed_mod->mod->name, word, word_len)) {
Michal Vaskoc3781c32020-10-06 14:04:08 +0200996 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Submodule \"belongs-to\" value \"%.*s\" does not match its module name \"%s\".",
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200997 (int)word_len, word, ctx->parsed_mod->mod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +0200998 free(buf);
999 return LY_EVALID;
1000 }
1001 free(buf);
Radek Krejcif09e4e82019-06-14 15:08:11 +02001002
Michal Vasko63f3d842020-07-08 10:10:14 +02001003 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001004 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001005 case LY_STMT_PREFIX:
Michal Vasko63f3d842020-07-08 10:10:14 +02001006 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001007 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001008 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001009 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001010 break;
1011 default:
David Sedlákb3077192019-06-19 10:55:37 +02001012 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001013 return LY_EVALID;
1014 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001015 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001016 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001017checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001018 /* mandatory substatements */
1019 if (!*prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02001020 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001021 return LY_EVALID;
1022 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001023 return ret;
1024}
1025
Michal Vaskoea5abea2018-09-18 13:10:54 +02001026/**
1027 * @brief Parse the revision-date statement.
1028 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001029 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001030 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001031 * @param[in,out] rev Array to store the parsed value in.
1032 * @param[in,out] exts Extension instances to add to.
1033 *
1034 * @return LY_ERR values.
1035 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001036static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001037parse_revisiondate(struct lys_yang_parser_ctx *ctx, struct ly_in *in, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001038{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001039 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001040 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001041 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001042 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001043
1044 if (rev[0]) {
David Sedlákb3077192019-06-19 10:55:37 +02001045 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001046 return LY_EVALID;
1047 }
1048
1049 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001050 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001051
1052 /* check value */
Michal Vaskob36053d2020-03-26 15:49:30 +01001053 if (lysp_check_date((struct lys_parser_ctx *)ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001054 free(buf);
1055 return LY_EVALID;
1056 }
1057
1058 /* store value and spend buf if allocated */
1059 strncpy(rev, word, word_len);
1060 free(buf);
1061
Michal Vaskod989ba02020-08-24 10:59:24 +02001062 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001063 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001064 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001065 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001066 break;
1067 default:
David Sedlákb3077192019-06-19 10:55:37 +02001068 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001069 return LY_EVALID;
1070 }
1071 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001072 return ret;
1073}
1074
Michal Vaskoea5abea2018-09-18 13:10:54 +02001075/**
1076 * @brief Parse the include statement.
1077 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001078 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001079 * @param[in] module_name Name of the module to check name collisions.
Michal Vasko63f3d842020-07-08 10:10:14 +02001080 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001081 * @param[in,out] includes Parsed includes to add to.
1082 *
1083 * @return LY_ERR values.
1084 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001085static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001086parse_include(struct lys_yang_parser_ctx *ctx, const char *module_name, struct ly_in *in, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001087{
Radek Krejcid33273d2018-10-25 14:55:52 +02001088 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001089 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001090 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001091 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001092 struct lysp_include *inc;
1093
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001094 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001095
1096 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001097 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001098
Radek Krejci011e4aa2020-09-04 15:22:31 +02001099 INSERT_WORD_RET(ctx, buf, inc->name, word, word_len);
Radek Krejci086c7132018-10-26 15:29:04 +02001100
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001101 /* submodules share the namespace with the module names, so there must not be
1102 * a module of the same name in the context, no need for revision matching */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001103 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(PARSER_CTX(ctx), inc->name)) {
David Sedlákb3077192019-06-19 10:55:37 +02001104 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001105 return LY_EVALID;
1106 }
1107
Michal Vaskod989ba02020-08-24 10:59:24 +02001108 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001109 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001110 case LY_STMT_DESCRIPTION:
Radek Krejci335332a2019-09-05 13:03:35 +02001111 PARSER_CHECK_STMTVER2_RET(ctx, "description", "include");
Michal Vasko63f3d842020-07-08 10:10:14 +02001112 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001113 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001114 case LY_STMT_REFERENCE:
Radek Krejci335332a2019-09-05 13:03:35 +02001115 PARSER_CHECK_STMTVER2_RET(ctx, "reference", "include");
Michal Vasko63f3d842020-07-08 10:10:14 +02001116 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001117 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001118 case LY_STMT_REVISION_DATE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001119 LY_CHECK_RET(parse_revisiondate(ctx, in, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001120 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001121 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001122 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001123 break;
1124 default:
David Sedlákb3077192019-06-19 10:55:37 +02001125 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001126 return LY_EVALID;
1127 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001128 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001129 return ret;
1130}
1131
Michal Vaskoea5abea2018-09-18 13:10:54 +02001132/**
1133 * @brief Parse the import statement.
1134 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001135 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001136 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vasko63f3d842020-07-08 10:10:14 +02001137 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001138 * @param[in,out] imports Parsed imports to add to.
1139 *
1140 * @return LY_ERR values.
1141 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001142static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001143parse_import(struct lys_yang_parser_ctx *ctx, const char *module_prefix, struct ly_in *in, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001144{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001145 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001146 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001147 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001148 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001149 struct lysp_import *imp;
1150
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001151 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001152
1153 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001154 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001155 INSERT_WORD_RET(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001156
Michal Vasko63f3d842020-07-08 10:10:14 +02001157 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001158 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001159 case LY_STMT_PREFIX:
Michal Vasko63f3d842020-07-08 10:10:14 +02001160 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
Michal Vaskob36053d2020-03-26 15:49:30 +01001161 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 +02001162 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001163 case LY_STMT_DESCRIPTION:
Radek Krejci335332a2019-09-05 13:03:35 +02001164 PARSER_CHECK_STMTVER2_RET(ctx, "description", "import");
Michal Vasko63f3d842020-07-08 10:10:14 +02001165 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001166 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001167 case LY_STMT_REFERENCE:
Radek Krejci335332a2019-09-05 13:03:35 +02001168 PARSER_CHECK_STMTVER2_RET(ctx, "reference", "import");
Michal Vasko63f3d842020-07-08 10:10:14 +02001169 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001170 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001171 case LY_STMT_REVISION_DATE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001172 LY_CHECK_RET(parse_revisiondate(ctx, in, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001173 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001174 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001175 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001176 break;
1177 default:
David Sedlákb3077192019-06-19 10:55:37 +02001178 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001179 return LY_EVALID;
1180 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001181 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001182 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001183checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184 /* mandatory substatements */
David Sedlákb3077192019-06-19 10:55:37 +02001185 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001186
1187 return ret;
1188}
1189
Michal Vaskoea5abea2018-09-18 13:10:54 +02001190/**
1191 * @brief Parse the revision statement.
1192 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001193 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001194 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001195 * @param[in,out] revs Parsed revisions to add to.
1196 *
1197 * @return LY_ERR values.
1198 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001199static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001200parse_revision(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001201{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001202 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001203 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001204 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001205 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001206 struct lysp_revision *rev;
1207
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001208 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001209
1210 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001211 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001212
1213 /* check value */
Michal Vaskob36053d2020-03-26 15:49:30 +01001214 if (lysp_check_date((struct lys_parser_ctx *)ctx, word, word_len, "revision")) {
David Sedlák68ef3dc2019-07-22 13:40:19 +02001215 free(buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001216 return LY_EVALID;
1217 }
1218
Radek Krejcib7db73a2018-10-24 14:18:40 +02001219 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001220 free(buf);
1221
Michal Vaskod989ba02020-08-24 10:59:24 +02001222 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001223 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001224 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02001225 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001226 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001227 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001228 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001229 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001230 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001231 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001232 break;
1233 default:
David Sedlákb3077192019-06-19 10:55:37 +02001234 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001235 return LY_EVALID;
1236 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001237 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001238 return ret;
1239}
1240
Michal Vaskoea5abea2018-09-18 13:10:54 +02001241/**
1242 * @brief Parse a generic text field that can have more instances such as base.
1243 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001244 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001245 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001246 * @param[in] substmt Type of this substatement.
1247 * @param[in,out] texts Parsed values to add to.
1248 * @param[in] arg Type of the expected argument.
1249 * @param[in,out] exts Extension instances to add to.
1250 *
1251 * @return LY_ERR values.
1252 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001253static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001254parse_text_fields(struct lys_yang_parser_ctx *ctx, struct ly_in *in, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
Radek Krejci0f969882020-08-21 16:56:47 +02001255 struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001256{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001257 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001258 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001259 const char **item;
1260 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001261 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001262
1263 /* allocate new pointer */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001264 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001265
1266 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001267 LY_CHECK_RET(get_argument(ctx, in, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001268
Radek Krejci011e4aa2020-09-04 15:22:31 +02001269 INSERT_WORD_RET(ctx, buf, *item, word, word_len);
Michal Vaskod989ba02020-08-24 10:59:24 +02001270 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001271 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001272 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001273 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, substmt, LY_ARRAY_COUNT(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001274 break;
1275 default:
David Sedlákb3077192019-06-19 10:55:37 +02001276 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001277 return LY_EVALID;
1278 }
1279 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001280 return ret;
1281}
1282
Michal Vaskoea5abea2018-09-18 13:10:54 +02001283/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02001284 * @brief Parse a generic text field that can have more instances such as base.
1285 *
1286 * @param[in] ctx yang parser context for logging.
1287 * @param[in,out] in Input structure.
1288 * @param[in] substmt Type of this substatement.
1289 * @param[in,out] qnames Parsed qnames to add to.
1290 * @param[in] arg Type of the expected argument.
1291 * @param[in,out] exts Extension instances to add to.
1292 *
1293 * @return LY_ERR values.
1294 */
1295static LY_ERR
1296parse_qnames(struct lys_yang_parser_ctx *ctx, struct ly_in *in, LYEXT_SUBSTMT substmt, struct lysp_qname **qnames,
1297 enum yang_arg arg, struct lysp_ext_instance **exts)
1298{
1299 LY_ERR ret = LY_SUCCESS;
1300 char *buf, *word;
1301 struct lysp_qname *item;
1302 size_t word_len;
1303 enum ly_stmt kw;
1304
1305 /* allocate new pointer */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001306 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001307
1308 /* get value */
1309 LY_CHECK_RET(get_argument(ctx, in, arg, NULL, &word, &buf, &word_len));
1310
1311 INSERT_WORD_RET(ctx, buf, item->str, word, word_len);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001312 item->mod = ctx->parsed_mod;
Michal Vasko7f45cf22020-10-01 12:49:44 +02001313 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
1314 switch (kw) {
1315 case LY_STMT_EXTENSION_INSTANCE:
1316 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, substmt, LY_ARRAY_COUNT(*qnames) - 1, exts));
1317 break;
1318 default:
1319 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
1320 return LY_EVALID;
1321 }
1322 }
1323 return ret;
1324}
1325
1326/**
Michal Vaskoea5abea2018-09-18 13:10:54 +02001327 * @brief Parse the config statement.
1328 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001329 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001330 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001331 * @param[in,out] flags Flags to add to.
1332 * @param[in,out] exts Extension instances to add to.
1333 *
1334 * @return LY_ERR values.
1335 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001336static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001337parse_config(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001338{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001339 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001340 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001341 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001342 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001343
1344 if (*flags & LYS_CONFIG_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001345 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001346 return LY_EVALID;
1347 }
1348
1349 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001350 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001351
Radek Krejcif13b87b2020-12-01 22:02:17 +01001352 if ((word_len == ly_strlen_const("true")) && !strncmp(word, "true", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001353 *flags |= LYS_CONFIG_W;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001354 } else if ((word_len == ly_strlen_const("false")) && !strncmp(word, "false", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001355 *flags |= LYS_CONFIG_R;
1356 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001357 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001358 free(buf);
1359 return LY_EVALID;
1360 }
1361 free(buf);
1362
Michal Vaskod989ba02020-08-24 10:59:24 +02001363 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001364 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001365 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001366 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001367 break;
1368 default:
David Sedlákb3077192019-06-19 10:55:37 +02001369 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001370 return LY_EVALID;
1371 }
1372 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001373 return ret;
1374}
1375
Michal Vaskoea5abea2018-09-18 13:10:54 +02001376/**
1377 * @brief Parse the mandatory statement.
1378 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001379 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001380 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001381 * @param[in,out] flags Flags to add to.
1382 * @param[in,out] exts Extension instances to add to.
1383 *
1384 * @return LY_ERR values.
1385 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001386static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001387parse_mandatory(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001388{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001389 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001390 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001391 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001392 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001393
1394 if (*flags & LYS_MAND_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001395 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001396 return LY_EVALID;
1397 }
1398
1399 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001400 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001401
Radek Krejcif13b87b2020-12-01 22:02:17 +01001402 if ((word_len == ly_strlen_const("true")) && !strncmp(word, "true", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001403 *flags |= LYS_MAND_TRUE;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001404 } else if ((word_len == ly_strlen_const("false")) && !strncmp(word, "false", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001405 *flags |= LYS_MAND_FALSE;
1406 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001407 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001408 free(buf);
1409 return LY_EVALID;
1410 }
1411 free(buf);
1412
Michal Vaskod989ba02020-08-24 10:59:24 +02001413 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001414 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001415 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001416 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001417 break;
1418 default:
David Sedlákb3077192019-06-19 10:55:37 +02001419 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001420 return LY_EVALID;
1421 }
1422 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001423 return ret;
1424}
1425
Michal Vaskoea5abea2018-09-18 13:10:54 +02001426/**
1427 * @brief Parse a restriction such as range or length.
1428 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001429 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001430 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001431 * @param[in] restr_kw Type of this particular restriction.
1432 * @param[in,out] exts Extension instances to add to.
1433 *
1434 * @return LY_ERR values.
1435 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001436static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001437parse_restr(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt restr_kw, struct lysp_restr *restr)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001439 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001440 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001441 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001442 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001443
1444 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001445 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001446
Michal Vaskob36053d2020-03-26 15:49:30 +01001447 CHECK_NONEMPTY(ctx, word_len, ly_stmt2str(restr_kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +02001448 INSERT_WORD_RET(ctx, buf, restr->arg.str, word, word_len);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001449 restr->arg.mod = ctx->parsed_mod;
Michal Vaskod989ba02020-08-24 10:59:24 +02001450 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001451 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001452 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02001453 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001454 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001455 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001456 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001457 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001458 case LY_STMT_ERROR_APP_TAG:
Michal Vasko63f3d842020-07-08 10:10:14 +02001459 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001460 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001461 case LY_STMT_ERROR_MESSAGE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001462 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001463 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001464 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001465 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001466 break;
1467 default:
David Sedlákb3077192019-06-19 10:55:37 +02001468 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001469 return LY_EVALID;
1470 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001471 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001472 return ret;
1473}
1474
Michal Vaskoea5abea2018-09-18 13:10:54 +02001475/**
1476 * @brief Parse a restriction that can have more instances such as must.
1477 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001478 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001479 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001480 * @param[in] restr_kw Type of this particular restriction.
1481 * @param[in,out] restrs Restrictions to add to.
1482 *
1483 * @return LY_ERR values.
1484 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001485static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001486parse_restrs(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt restr_kw, struct lysp_restr **restrs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001487{
1488 struct lysp_restr *restr;
1489
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001490 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *restrs, restr, LY_EMEM);
Michal Vasko63f3d842020-07-08 10:10:14 +02001491 return parse_restr(ctx, in, restr_kw, restr);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001492}
1493
Michal Vaskoea5abea2018-09-18 13:10:54 +02001494/**
1495 * @brief Parse the status statement.
1496 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001497 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001498 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001499 * @param[in,out] flags Flags to add to.
1500 * @param[in,out] exts Extension instances to add to.
1501 *
1502 * @return LY_ERR values.
1503 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001504static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001505parse_status(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001506{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001507 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001508 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001509 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001510 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001511
1512 if (*flags & LYS_STATUS_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001513 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001514 return LY_EVALID;
1515 }
1516
1517 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001518 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001519
Radek Krejcif13b87b2020-12-01 22:02:17 +01001520 if ((word_len == ly_strlen_const("current")) && !strncmp(word, "current", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001521 *flags |= LYS_STATUS_CURR;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001522 } else if ((word_len == ly_strlen_const("deprecated")) && !strncmp(word, "deprecated", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001523 *flags |= LYS_STATUS_DEPRC;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001524 } else if ((word_len == ly_strlen_const("obsolete")) && !strncmp(word, "obsolete", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001525 *flags |= LYS_STATUS_OBSLT;
1526 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001527 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001528 free(buf);
1529 return LY_EVALID;
1530 }
1531 free(buf);
1532
Michal Vaskod989ba02020-08-24 10:59:24 +02001533 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001534 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001535 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001536 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001537 break;
1538 default:
David Sedlákb3077192019-06-19 10:55:37 +02001539 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001540 return LY_EVALID;
1541 }
1542 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001543 return ret;
1544}
1545
Michal Vaskoea5abea2018-09-18 13:10:54 +02001546/**
1547 * @brief Parse the when statement.
1548 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001549 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001550 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001551 * @param[in,out] when_p When pointer to parse to.
1552 *
1553 * @return LY_ERR values.
1554 */
Radek Krejcif09e4e82019-06-14 15:08:11 +02001555LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001556parse_when(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001557{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001558 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001559 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001560 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001561 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001562 struct lysp_when *when;
1563
1564 if (*when_p) {
David Sedlákb3077192019-06-19 10:55:37 +02001565 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001566 return LY_EVALID;
1567 }
1568
1569 when = calloc(1, sizeof *when);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001570 LY_CHECK_ERR_RET(!when, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +02001571 *when_p = when;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001572
1573 /* get value */
Radek Krejci011e4aa2020-09-04 15:22:31 +02001574 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vaskob36053d2020-03-26 15:49:30 +01001575 CHECK_NONEMPTY(ctx, word_len, "when");
Radek Krejci011e4aa2020-09-04 15:22:31 +02001576 INSERT_WORD_RET(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001577
Michal Vaskod989ba02020-08-24 10:59:24 +02001578 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001579 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001580 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02001581 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001582 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001583 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001584 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001585 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001586 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001587 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001588 break;
1589 default:
David Sedlákb3077192019-06-19 10:55:37 +02001590 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001591 return LY_EVALID;
1592 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001593 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001594 return ret;
1595}
1596
Michal Vaskoea5abea2018-09-18 13:10:54 +02001597/**
1598 * @brief Parse the anydata or anyxml statement.
1599 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001600 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001601 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001602 * @param[in] kw Type of this particular keyword.
1603 * @param[in,out] siblings Siblings to add to.
1604 *
1605 * @return LY_ERR values.
1606 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02001607LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001608parse_any(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt kw, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001609{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001610 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001611 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001612 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001613 struct lysp_node_anydata *any;
1614
David Sedlák60adc092019-08-06 15:57:02 +02001615 /* create new structure and insert into siblings */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001616 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, any, next, LY_EMEM);
David Sedlák60adc092019-08-06 15:57:02 +02001617
Radek Krejcid6b76452019-09-03 17:03:03 +02001618 any->nodetype = kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001619 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001620
Michal Vasko7fbc8162018-09-17 10:35:16 +02001621 /* get name */
Michal Vasko63f3d842020-07-08 10:10:14 +02001622 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02001623 INSERT_WORD_RET(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001624
1625 /* parse substatements */
Michal Vaskod989ba02020-08-24 10:59:24 +02001626 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001627 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001628 case LY_STMT_CONFIG:
Michal Vasko63f3d842020-07-08 10:10:14 +02001629 LY_CHECK_RET(parse_config(ctx, in, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001630 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001631 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02001632 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001633 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001634 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02001635 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001636 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001637 case LY_STMT_MANDATORY:
Michal Vasko63f3d842020-07-08 10:10:14 +02001638 LY_CHECK_RET(parse_mandatory(ctx, in, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001639 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001640 case LY_STMT_MUST:
Michal Vasko63f3d842020-07-08 10:10:14 +02001641 LY_CHECK_RET(parse_restrs(ctx, in, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001642 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001643 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001644 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001645 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001646 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02001647 LY_CHECK_RET(parse_status(ctx, in, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001648 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001649 case LY_STMT_WHEN:
Michal Vasko63f3d842020-07-08 10:10:14 +02001650 LY_CHECK_RET(parse_when(ctx, in, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001651 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001652 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001653 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001654 break;
1655 default:
David Sedlákb3077192019-06-19 10:55:37 +02001656 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejci0f969882020-08-21 16:56:47 +02001657 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(LY_STMT_ANYDATA) : ly_stmt2str(LY_STMT_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001658 return LY_EVALID;
1659 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001660 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001661 return ret;
1662}
1663
Michal Vaskoea5abea2018-09-18 13:10:54 +02001664/**
1665 * @brief Parse the value or position statement. Substatement of type enum statement.
1666 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001667 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001668 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001669 * @param[in] val_kw Type of this particular keyword.
1670 * @param[in,out] value Value to write to.
1671 * @param[in,out] flags Flags to write to.
1672 * @param[in,out] exts Extension instances to add to.
1673 *
1674 * @return LY_ERR values.
1675 */
David Sedlákd6ce6d72019-07-16 17:30:18 +02001676LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001677parse_type_enum_value_pos(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt val_kw, int64_t *value, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +02001678 struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001679{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001680 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001681 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001682 size_t word_len;
Radek Krejci4ad42aa2019-07-23 16:55:58 +02001683 long int num = 0;
1684 unsigned long int unum = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001685 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001686
1687 if (*flags & LYS_SET_VALUE) {
David Sedlákb3077192019-06-19 10:55:37 +02001688 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001689 return LY_EVALID;
1690 }
1691 *flags |= LYS_SET_VALUE;
1692
1693 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001694 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001695
Radek Krejcid6b76452019-09-03 17:03:03 +02001696 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 +02001697 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001698 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001699 }
1700
1701 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001702 if (val_kw == LY_STMT_VALUE) {
Radek Krejcif13b87b2020-12-01 22:02:17 +01001703 num = strtol(word, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001704 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
David Sedlákb3077192019-06-19 10:55:37 +02001705 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001706 goto error;
1707 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001708 } else {
Radek Krejcif13b87b2020-12-01 22:02:17 +01001709 unum = strtoul(word, &ptr, LY_BASE_DEC);
Radek Krejci8b764662018-11-14 14:15:13 +01001710 if (unum > UINT64_C(4294967295)) {
David Sedlákb3077192019-06-19 10:55:37 +02001711 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001712 goto error;
1713 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001714 }
1715 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001716 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001717 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001718 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001719 }
1720 if (errno == ERANGE) {
David Sedlákb3077192019-06-19 10:55:37 +02001721 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001722 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001723 }
Radek Krejcid6b76452019-09-03 17:03:03 +02001724 if (val_kw == LY_STMT_VALUE) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001725 *value = num;
1726 } else {
1727 *value = unum;
1728 }
1729 free(buf);
1730
Michal Vaskod989ba02020-08-24 10:59:24 +02001731 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001732 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001733 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001734 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, val_kw == LY_STMT_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001735 break;
1736 default:
David Sedlákb3077192019-06-19 10:55:37 +02001737 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001738 return LY_EVALID;
1739 }
1740 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001741 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001742
1743error:
1744 free(buf);
1745 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001746}
1747
Michal Vaskoea5abea2018-09-18 13:10:54 +02001748/**
1749 * @brief Parse the enum or bit statement. Substatement of type statement.
1750 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001751 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001752 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001753 * @param[in] enum_kw Type of this particular keyword.
1754 * @param[in,out] enums Enums or bits to add to.
1755 *
1756 * @return LY_ERR values.
1757 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001758static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001759parse_type_enum(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt enum_kw, struct lysp_type_enum **enums)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001760{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001761 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001762 char *buf, *word;
David Sedlák6544c182019-07-12 13:17:33 +02001763 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001764 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001765 struct lysp_type_enum *enm;
1766
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001767 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001768
1769 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001770 LY_CHECK_RET(get_argument(ctx, in, enum_kw == LY_STMT_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejcid6b76452019-09-03 17:03:03 +02001771 if (enum_kw == LY_STMT_ENUM) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001772 ret = lysp_check_enum_name((struct lys_parser_ctx *)ctx, (const char *)word, word_len);
David Sedlák6544c182019-07-12 13:17:33 +02001773 LY_CHECK_ERR_RET(ret, free(buf), ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001774 } /* else nothing specific for YANG_BIT */
Radek Krejci8b764662018-11-14 14:15:13 +01001775
Radek Krejci011e4aa2020-09-04 15:22:31 +02001776 INSERT_WORD_RET(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001777 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1778
Michal Vaskod989ba02020-08-24 10:59:24 +02001779 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001780 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001781 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02001782 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001783 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001784 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02001785 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Michal Vasko7f45cf22020-10-01 12:49:44 +02001786 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001787 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001788 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001789 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001790 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001791 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02001792 LY_CHECK_RET(parse_status(ctx, in, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001793 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001794 case LY_STMT_VALUE:
1795 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 +02001796 ly_stmt2str(enum_kw)), LY_EVALID);
Michal Vasko63f3d842020-07-08 10:10:14 +02001797 LY_CHECK_RET(parse_type_enum_value_pos(ctx, in, kw, &enm->value, &enm->flags, &enm->exts));
David Sedlák9fb515f2019-07-11 10:33:58 +02001798 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001799 case LY_STMT_POSITION:
1800 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 +02001801 ly_stmt2str(enum_kw)), LY_EVALID);
Michal Vasko63f3d842020-07-08 10:10:14 +02001802 LY_CHECK_RET(parse_type_enum_value_pos(ctx, in, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001803 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001804 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001805 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001806 break;
1807 default:
David Sedlákb3077192019-06-19 10:55:37 +02001808 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001809 return LY_EVALID;
1810 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001811 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001812 return ret;
1813}
1814
Michal Vaskoea5abea2018-09-18 13:10:54 +02001815/**
1816 * @brief Parse the fraction-digits statement. Substatement of type statement.
1817 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001818 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001819 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001820 * @param[in,out] fracdig Value to write to.
1821 * @param[in,out] exts Extension instances to add to.
1822 *
1823 * @return LY_ERR values.
1824 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001825static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001826parse_type_fracdigits(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint8_t *fracdig, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001827{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001828 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001829 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001830 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001831 unsigned long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02001832 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001833
1834 if (*fracdig) {
David Sedlákb3077192019-06-19 10:55:37 +02001835 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001836 return LY_EVALID;
1837 }
1838
1839 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001840 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001841
1842 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
David Sedlákb3077192019-06-19 10:55:37 +02001843 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001844 free(buf);
1845 return LY_EVALID;
1846 }
1847
1848 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001849 num = strtoul(word, &ptr, LY_BASE_DEC);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001850 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001851 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001852 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001853 free(buf);
1854 return LY_EVALID;
1855 }
Radek Krejcif13b87b2020-12-01 22:02:17 +01001856 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02001857 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001858 free(buf);
1859 return LY_EVALID;
1860 }
1861 *fracdig = num;
1862 free(buf);
1863
Michal Vaskod989ba02020-08-24 10:59:24 +02001864 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001865 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001866 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001867 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001868 break;
1869 default:
David Sedlákb3077192019-06-19 10:55:37 +02001870 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001871 return LY_EVALID;
1872 }
1873 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001874 return ret;
1875}
1876
Michal Vaskoea5abea2018-09-18 13:10:54 +02001877/**
1878 * @brief Parse the require-instance statement. Substatement of type statement.
1879 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001880 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001881 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001882 * @param[in,out] reqinst Value to write to.
1883 * @param[in,out] flags Flags to write to.
1884 * @param[in,out] exts Extension instances to add to.
1885 *
1886 * @return LY_ERR values.
1887 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001888static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001889parse_type_reqinstance(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint8_t *reqinst, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +02001890 struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001891{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001892 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001893 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001894 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001895 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001896
1897 if (*flags & LYS_SET_REQINST) {
David Sedlákb3077192019-06-19 10:55:37 +02001898 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001899 return LY_EVALID;
1900 }
1901 *flags |= LYS_SET_REQINST;
1902
1903 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001904 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001905
Radek Krejcif13b87b2020-12-01 22:02:17 +01001906 if ((word_len == ly_strlen_const("true")) && !strncmp(word, "true", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001907 *reqinst = 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001908 } else if ((word_len != ly_strlen_const("false")) || strncmp(word, "false", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02001909 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001910 free(buf);
1911 return LY_EVALID;
1912 }
1913 free(buf);
1914
Michal Vaskod989ba02020-08-24 10:59:24 +02001915 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001916 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001917 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001918 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001919 break;
1920 default:
David Sedlákb3077192019-06-19 10:55:37 +02001921 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001922 return LY_EVALID;
1923 }
1924 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001925 return ret;
1926}
1927
Michal Vaskoea5abea2018-09-18 13:10:54 +02001928/**
1929 * @brief Parse the modifier statement. Substatement of type pattern statement.
1930 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001931 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001932 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001933 * @param[in,out] pat Value to write to.
1934 * @param[in,out] exts Extension instances to add to.
1935 *
1936 * @return LY_ERR values.
1937 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001938static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001939parse_type_pattern_modifier(struct lys_yang_parser_ctx *ctx, struct ly_in *in, const char **pat,
Radek Krejci0f969882020-08-21 16:56:47 +02001940 struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001941{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001942 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001943 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001944 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001945 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001946
Radek Krejcif13b87b2020-12-01 22:02:17 +01001947 if ((*pat)[0] == LYSP_RESTR_PATTERN_NACK) {
David Sedlákb3077192019-06-19 10:55:37 +02001948 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001949 return LY_EVALID;
1950 }
1951
1952 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02001953 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001954
Radek Krejcif13b87b2020-12-01 22:02:17 +01001955 if ((word_len != ly_strlen_const("invert-match")) || strncmp(word, "invert-match", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02001956 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001957 free(buf);
1958 return LY_EVALID;
1959 }
1960 free(buf);
1961
1962 /* replace the value in the dictionary */
1963 buf = malloc(strlen(*pat) + 1);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001964 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001965 strcpy(buf, *pat);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001966 lydict_remove(PARSER_CTX(ctx), *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001967
Radek Krejcif13b87b2020-12-01 22:02:17 +01001968 assert(buf[0] == LYSP_RESTR_PATTERN_ACK);
1969 buf[0] = LYSP_RESTR_PATTERN_NACK;
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001970 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, pat));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001971
Michal Vaskod989ba02020-08-24 10:59:24 +02001972 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001973 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001974 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02001975 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001976 break;
1977 default:
David Sedlákb3077192019-06-19 10:55:37 +02001978 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001979 return LY_EVALID;
1980 }
1981 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001982 return ret;
1983}
1984
Michal Vaskoea5abea2018-09-18 13:10:54 +02001985/**
1986 * @brief Parse the pattern statement. Substatement of type statement.
1987 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001988 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02001989 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001990 * @param[in,out] patterns Restrictions to add to.
1991 *
1992 * @return LY_ERR values.
1993 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001994static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001995parse_type_pattern(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001996{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001997 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001998 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001999 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002000 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002001 struct lysp_restr *restr;
2002
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002003 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002004
2005 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02002006 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002007
2008 /* add special meaning first byte */
2009 if (buf) {
Radek Krejcif13b87b2020-12-01 22:02:17 +01002010 buf = ly_realloc(buf, word_len + 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002011 word = buf;
2012 } else {
2013 buf = malloc(word_len + 2);
2014 }
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002015 LY_CHECK_ERR_RET(!buf, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002016 memmove(buf + 1, word, word_len);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002017 buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
Radek Krejci86d106e2018-10-18 09:53:19 +02002018 buf[word_len + 1] = '\0'; /* terminating NULL byte */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002019 LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
2020 restr->arg.mod = ctx->parsed_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002021
Michal Vaskod989ba02020-08-24 10:59:24 +02002022 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002023 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002024 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02002025 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002026 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002027 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002028 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002029 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002030 case LY_STMT_ERROR_APP_TAG:
Michal Vasko63f3d842020-07-08 10:10:14 +02002031 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002032 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002033 case LY_STMT_ERROR_MESSAGE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002034 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002035 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002036 case LY_STMT_MODIFIER:
Radek Krejci335332a2019-09-05 13:03:35 +02002037 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Michal Vasko7f45cf22020-10-01 12:49:44 +02002038 LY_CHECK_RET(parse_type_pattern_modifier(ctx, in, &restr->arg.str, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002039 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002040 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002041 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002042 break;
2043 default:
David Sedlákb3077192019-06-19 10:55:37 +02002044 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002045 return LY_EVALID;
2046 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002047 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002048 return ret;
2049}
2050
Michal Vaskoea5abea2018-09-18 13:10:54 +02002051/**
2052 * @brief Parse the type statement.
2053 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002054 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002055 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002056 * @param[in,out] type Type to wrote to.
2057 *
2058 * @return LY_ERR values.
2059 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002060static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02002061parse_type(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002062{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002063 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002064 char *buf, *word;
Michal Vasko004d3152020-06-11 19:59:22 +02002065 const char *str_path = NULL;
Radek Krejciefd22f62018-09-27 11:47:58 +02002066 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002067 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002068 struct lysp_type *nest_type;
2069
2070 if (type->name) {
David Sedlákb3077192019-06-19 10:55:37 +02002071 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002072 return LY_EVALID;
2073 }
2074
2075 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02002076 LY_CHECK_RET(get_argument(ctx, in, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02002077 INSERT_WORD_RET(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002078
Michal Vaskoe9c050f2020-10-06 14:01:23 +02002079 /* set module */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002080 type->pmod = ctx->parsed_mod;
Michal Vaskoe9c050f2020-10-06 14:01:23 +02002081
Michal Vaskod989ba02020-08-24 10:59:24 +02002082 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002083 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002084 case LY_STMT_BASE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002085 LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002086 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002087 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002088 case LY_STMT_BIT:
Michal Vasko63f3d842020-07-08 10:10:14 +02002089 LY_CHECK_RET(parse_type_enum(ctx, in, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002090 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002091 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002092 case LY_STMT_ENUM:
Michal Vasko63f3d842020-07-08 10:10:14 +02002093 LY_CHECK_RET(parse_type_enum(ctx, in, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002094 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002095 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002096 case LY_STMT_FRACTION_DIGITS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002097 LY_CHECK_RET(parse_type_fracdigits(ctx, in, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002098 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002099 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002100 case LY_STMT_LENGTH:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002101 if (type->length) {
David Sedlákb3077192019-06-19 10:55:37 +02002102 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002103 return LY_EVALID;
2104 }
2105 type->length = calloc(1, sizeof *type->length);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002106 LY_CHECK_ERR_RET(!type->length, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002107
Michal Vasko63f3d842020-07-08 10:10:14 +02002108 LY_CHECK_RET(parse_restr(ctx, in, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002109 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002110 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002111 case LY_STMT_PATH:
Michal Vasko004d3152020-06-11 19:59:22 +02002112 if (type->path) {
2113 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(LYEXT_SUBSTMT_PATH));
2114 return LY_EVALID;
2115 }
2116
Michal Vasko63f3d842020-07-08 10:10:14 +02002117 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PATH, 0, &str_path, Y_STR_ARG, &type->exts));
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002118 ret = ly_path_parse(PARSER_CTX(ctx), NULL, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
Michal Vasko69730152020-10-09 16:30:07 +02002119 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002120 lydict_remove(PARSER_CTX(ctx), str_path);
Michal Vasko004d3152020-06-11 19:59:22 +02002121 LY_CHECK_RET(ret);
Radek Krejcid505e3d2018-11-13 09:04:17 +01002122 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002123 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002124 case LY_STMT_PATTERN:
Michal Vasko63f3d842020-07-08 10:10:14 +02002125 LY_CHECK_RET(parse_type_pattern(ctx, in, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002126 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002127 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002128 case LY_STMT_RANGE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002129 if (type->range) {
David Sedlákb3077192019-06-19 10:55:37 +02002130 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002131 return LY_EVALID;
2132 }
2133 type->range = calloc(1, sizeof *type->range);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002134 LY_CHECK_ERR_RET(!type->range, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002135
Michal Vasko63f3d842020-07-08 10:10:14 +02002136 LY_CHECK_RET(parse_restr(ctx, in, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002137 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002138 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002139 case LY_STMT_REQUIRE_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002140 LY_CHECK_RET(parse_type_reqinstance(ctx, in, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002141 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002142 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002143 case LY_STMT_TYPE:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002144 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), type->types, nest_type, LY_EMEM);
Michal Vasko63f3d842020-07-08 10:10:14 +02002145 LY_CHECK_RET(parse_type(ctx, in, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002146 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002147 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002148 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002149 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002150 break;
2151 default:
David Sedlákb3077192019-06-19 10:55:37 +02002152 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002153 return LY_EVALID;
2154 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002155 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002156 return ret;
2157}
2158
Michal Vaskoea5abea2018-09-18 13:10:54 +02002159/**
2160 * @brief Parse the leaf statement.
2161 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002162 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002163 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002164 * @param[in,out] siblings Siblings to add to.
2165 *
2166 * @return LY_ERR values.
2167 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002168LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02002169parse_leaf(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002170{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002171 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002172 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002173 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002174 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002175 struct lysp_node_leaf *leaf;
2176
David Sedlák60adc092019-08-06 15:57:02 +02002177 /* create new leaf structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002178 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, leaf, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002179 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002180 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002181
Michal Vasko7fbc8162018-09-17 10:35:16 +02002182 /* get name */
Michal Vasko63f3d842020-07-08 10:10:14 +02002183 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02002184 INSERT_WORD_RET(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002185
2186 /* parse substatements */
Michal Vasko63f3d842020-07-08 10:10:14 +02002187 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002188 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002189 case LY_STMT_CONFIG:
Michal Vasko63f3d842020-07-08 10:10:14 +02002190 LY_CHECK_RET(parse_config(ctx, in, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002191 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002192 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02002193 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt.str, Y_STR_ARG, &leaf->exts));
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002194 leaf->dflt.mod = ctx->parsed_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002195 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002196 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02002197 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002198 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002199 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02002200 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002201 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002202 case LY_STMT_MANDATORY:
Michal Vasko63f3d842020-07-08 10:10:14 +02002203 LY_CHECK_RET(parse_mandatory(ctx, in, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002204 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002205 case LY_STMT_MUST:
Michal Vasko63f3d842020-07-08 10:10:14 +02002206 LY_CHECK_RET(parse_restrs(ctx, in, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002207 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002208 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002209 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002210 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002211 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002212 LY_CHECK_RET(parse_status(ctx, in, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002213 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002214 case LY_STMT_TYPE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002215 LY_CHECK_RET(parse_type(ctx, in, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002216 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002217 case LY_STMT_UNITS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002218 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002219 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002220 case LY_STMT_WHEN:
Michal Vasko63f3d842020-07-08 10:10:14 +02002221 LY_CHECK_RET(parse_when(ctx, in, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002222 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002223 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002224 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002225 break;
2226 default:
David Sedlákb3077192019-06-19 10:55:37 +02002227 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002228 return LY_EVALID;
2229 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002230 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002231 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002232checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002233 /* mandatory substatements */
2234 if (!leaf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002235 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002236 return LY_EVALID;
2237 }
2238
2239 return ret;
2240}
2241
Michal Vaskoea5abea2018-09-18 13:10:54 +02002242/**
2243 * @brief Parse the max-elements statement.
2244 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002245 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002246 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002247 * @param[in,out] max Value to write to.
2248 * @param[in,out] flags Flags to write to.
2249 * @param[in,out] exts Extension instances to add to.
2250 *
2251 * @return LY_ERR values.
2252 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002253LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02002254parse_maxelements(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint32_t *max, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +02002255 struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002256{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002257 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002258 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002259 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002260 unsigned long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02002261 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002262
2263 if (*flags & LYS_SET_MAX) {
David Sedlákb3077192019-06-19 10:55:37 +02002264 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002265 return LY_EVALID;
2266 }
2267 *flags |= LYS_SET_MAX;
2268
2269 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02002270 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002271
2272 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
David Sedlákb3077192019-06-19 10:55:37 +02002273 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002274 free(buf);
2275 return LY_EVALID;
2276 }
2277
Radek Krejci7f9b6512019-09-18 13:11:09 +02002278 if (ly_strncmp("unbounded", word, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002279 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002280 num = strtoul(word, &ptr, LY_BASE_DEC);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002281 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002282 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002283 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002284 free(buf);
2285 return LY_EVALID;
2286 }
2287 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002288 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002289 free(buf);
2290 return LY_EVALID;
2291 }
2292
2293 *max = num;
2294 }
2295 free(buf);
2296
Michal Vaskod989ba02020-08-24 10:59:24 +02002297 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002298 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002299 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002300 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002301 break;
2302 default:
David Sedlákb3077192019-06-19 10:55:37 +02002303 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002304 return LY_EVALID;
2305 }
2306 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002307 return ret;
2308}
2309
Michal Vaskoea5abea2018-09-18 13:10:54 +02002310/**
2311 * @brief Parse the min-elements statement.
2312 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002313 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002314 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002315 * @param[in,out] min Value to write to.
2316 * @param[in,out] flags Flags to write to.
2317 * @param[in,out] exts Extension instances to add to.
2318 *
2319 * @return LY_ERR values.
2320 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002321LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02002322parse_minelements(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint32_t *min, uint16_t *flags,
Radek Krejci0f969882020-08-21 16:56:47 +02002323 struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002324{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002325 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002326 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002327 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002328 unsigned long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02002329 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002330
2331 if (*flags & LYS_SET_MIN) {
David Sedlákb3077192019-06-19 10:55:37 +02002332 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002333 return LY_EVALID;
2334 }
2335 *flags |= LYS_SET_MIN;
2336
2337 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02002338 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002339
2340 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
David Sedlákb3077192019-06-19 10:55:37 +02002341 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002342 free(buf);
2343 return LY_EVALID;
2344 }
2345
2346 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002347 num = strtoul(word, &ptr, LY_BASE_DEC);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002348 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002349 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002350 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002351 free(buf);
2352 return LY_EVALID;
2353 }
2354 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002355 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002356 free(buf);
2357 return LY_EVALID;
2358 }
2359 *min = num;
2360 free(buf);
2361
Michal Vaskod989ba02020-08-24 10:59:24 +02002362 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002363 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002364 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002365 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002366 break;
2367 default:
David Sedlákb3077192019-06-19 10:55:37 +02002368 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002369 return LY_EVALID;
2370 }
2371 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002372 return ret;
2373}
2374
Michal Vaskoea5abea2018-09-18 13:10:54 +02002375/**
2376 * @brief Parse the ordered-by statement.
2377 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002378 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002379 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002380 * @param[in,out] flags Flags to write to.
2381 * @param[in,out] exts Extension instances to add to.
2382 *
2383 * @return LY_ERR values.
2384 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002385static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02002386parse_orderedby(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002387{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002388 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002389 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002390 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002391 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002392
2393 if (*flags & LYS_ORDBY_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02002394 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002395 return LY_EVALID;
2396 }
2397
2398 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02002399 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002400
Radek Krejcif13b87b2020-12-01 22:02:17 +01002401 if ((word_len == ly_strlen_const("system")) && !strncmp(word, "system", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002402 *flags |= LYS_ORDBY_SYSTEM;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002403 } else if ((word_len == ly_strlen_const("user")) && !strncmp(word, "user", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002404 *flags |= LYS_ORDBY_USER;
2405 } else {
David Sedlákb3077192019-06-19 10:55:37 +02002406 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002407 free(buf);
2408 return LY_EVALID;
2409 }
2410 free(buf);
2411
Michal Vaskod989ba02020-08-24 10:59:24 +02002412 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002413 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002414 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002415 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002416 break;
2417 default:
David Sedlákb3077192019-06-19 10:55:37 +02002418 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002419 return LY_EVALID;
2420 }
2421 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002422 return ret;
2423}
2424
Michal Vaskoea5abea2018-09-18 13:10:54 +02002425/**
2426 * @brief Parse the leaf-list statement.
2427 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002428 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002429 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002430 * @param[in,out] siblings Siblings to add to.
2431 *
2432 * @return LY_ERR values.
2433 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002434LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02002435parse_leaflist(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002436{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002437 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002438 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002439 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002440 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002441 struct lysp_node_leaflist *llist;
2442
David Sedlák60adc092019-08-06 15:57:02 +02002443 /* create new leaf-list structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002444 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, llist, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002445 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002446 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002447
Michal Vasko7fbc8162018-09-17 10:35:16 +02002448 /* get name */
Michal Vasko63f3d842020-07-08 10:10:14 +02002449 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02002450 INSERT_WORD_RET(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002451
2452 /* parse substatements */
Michal Vasko63f3d842020-07-08 10:10:14 +02002453 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002454 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002455 case LY_STMT_CONFIG:
Michal Vasko63f3d842020-07-08 10:10:14 +02002456 LY_CHECK_RET(parse_config(ctx, in, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002457 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002458 case LY_STMT_DEFAULT:
Radek Krejci335332a2019-09-05 13:03:35 +02002459 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Michal Vasko7f45cf22020-10-01 12:49:44 +02002460 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002461 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002462 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02002463 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002464 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002465 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02002466 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002467 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002468 case LY_STMT_MAX_ELEMENTS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002469 LY_CHECK_RET(parse_maxelements(ctx, in, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002470 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002471 case LY_STMT_MIN_ELEMENTS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002472 LY_CHECK_RET(parse_minelements(ctx, in, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002473 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002474 case LY_STMT_MUST:
Michal Vasko63f3d842020-07-08 10:10:14 +02002475 LY_CHECK_RET(parse_restrs(ctx, in, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002476 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002477 case LY_STMT_ORDERED_BY:
Michal Vasko63f3d842020-07-08 10:10:14 +02002478 LY_CHECK_RET(parse_orderedby(ctx, in, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002479 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002480 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002481 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002482 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002483 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002484 LY_CHECK_RET(parse_status(ctx, in, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002485 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002486 case LY_STMT_TYPE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002487 LY_CHECK_RET(parse_type(ctx, in, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002488 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002489 case LY_STMT_UNITS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002490 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002491 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002492 case LY_STMT_WHEN:
Michal Vasko63f3d842020-07-08 10:10:14 +02002493 LY_CHECK_RET(parse_when(ctx, in, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002494 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002495 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002496 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002497 break;
2498 default:
David Sedlákb3077192019-06-19 10:55:37 +02002499 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002500 return LY_EVALID;
2501 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002502 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002503 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002504checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002505 /* mandatory substatements */
2506 if (!llist->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002507 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002508 return LY_EVALID;
2509 }
2510
2511 return ret;
2512}
2513
Michal Vaskoea5abea2018-09-18 13:10:54 +02002514/**
2515 * @brief Parse the refine statement.
2516 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002517 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002518 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002519 * @param[in,out] refines Refines to add to.
2520 *
2521 * @return LY_ERR values.
2522 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002523static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02002524parse_refine(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_refine **refines)
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_refine *rf;
2531
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002532 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002533
2534 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02002535 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vaskob36053d2020-03-26 15:49:30 +01002536 CHECK_NONEMPTY(ctx, word_len, "refine");
Radek Krejci011e4aa2020-09-04 15:22:31 +02002537 INSERT_WORD_RET(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002538
Michal Vaskod989ba02020-08-24 10:59:24 +02002539 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002540 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002541 case LY_STMT_CONFIG:
Michal Vasko63f3d842020-07-08 10:10:14 +02002542 LY_CHECK_RET(parse_config(ctx, in, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002543 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002544 case LY_STMT_DEFAULT:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002545 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002546 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002547 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02002548 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002549 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002550 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02002551 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Michal Vasko7f45cf22020-10-01 12:49:44 +02002552 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002553 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002554 case LY_STMT_MAX_ELEMENTS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002555 LY_CHECK_RET(parse_maxelements(ctx, in, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002556 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002557 case LY_STMT_MIN_ELEMENTS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002558 LY_CHECK_RET(parse_minelements(ctx, in, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002559 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002560 case LY_STMT_MUST:
Michal Vasko63f3d842020-07-08 10:10:14 +02002561 LY_CHECK_RET(parse_restrs(ctx, in, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002562 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002563 case LY_STMT_MANDATORY:
Michal Vasko63f3d842020-07-08 10:10:14 +02002564 LY_CHECK_RET(parse_mandatory(ctx, in, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002565 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002566 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002567 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002568 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002569 case LY_STMT_PRESENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002570 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002571 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002572 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002573 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002574 break;
2575 default:
David Sedlákb3077192019-06-19 10:55:37 +02002576 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002577 return LY_EVALID;
2578 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002579 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002580 return ret;
2581}
2582
Michal Vaskoea5abea2018-09-18 13:10:54 +02002583/**
2584 * @brief Parse the typedef statement.
2585 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002586 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002587 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002588 * @param[in,out] typedefs Typedefs to add to.
2589 *
2590 * @return LY_ERR values.
2591 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002592static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02002593parse_typedef(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct ly_in *in, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002594{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002595 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002596 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002597 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002598 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002599 struct lysp_tpdf *tpdf;
2600
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002601 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002602
2603 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02002604 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02002605 INSERT_WORD_RET(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002606
2607 /* parse substatements */
Michal Vasko63f3d842020-07-08 10:10:14 +02002608 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002609 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002610 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02002611 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt.str, Y_STR_ARG, &tpdf->exts));
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002612 tpdf->dflt.mod = ctx->parsed_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002613 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002614 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02002615 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002616 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002617 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002618 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002619 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002620 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002621 LY_CHECK_RET(parse_status(ctx, in, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002622 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002623 case LY_STMT_TYPE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002624 LY_CHECK_RET(parse_type(ctx, in, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002625 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002626 case LY_STMT_UNITS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002627 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002628 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002629 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002630 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002631 break;
2632 default:
David Sedlákb3077192019-06-19 10:55:37 +02002633 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002634 return LY_EVALID;
2635 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002636 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002637 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002638checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002639 /* mandatory substatements */
2640 if (!tpdf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002641 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002642 return LY_EVALID;
2643 }
2644
Radek Krejcibbe09a92018-11-08 09:36:54 +01002645 /* store data for collision check */
Michal Vasko7f45cf22020-10-01 12:49:44 +02002646 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
Radek Krejciba03a5a2020-08-27 14:40:41 +02002647 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0, NULL));
Radek Krejcibbe09a92018-11-08 09:36:54 +01002648 }
2649
Michal Vasko7fbc8162018-09-17 10:35:16 +02002650 return ret;
2651}
2652
Michal Vaskoea5abea2018-09-18 13:10:54 +02002653/**
2654 * @brief Parse the input or output statement.
2655 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002656 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002657 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002658 * @param[in] kw Type of this particular keyword
2659 * @param[in,out] inout_p Input/output pointer to write to.
2660 *
2661 * @return LY_ERR values.
2662 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002663static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02002664parse_inout(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt inout_kw, struct lysp_node *parent,
2665 struct lysp_action_inout *inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002666{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002667 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002668 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002669 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002670 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002671
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002672 if (inout_p->nodetype) {
David Sedlákb3077192019-06-19 10:55:37 +02002673 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002674 return LY_EVALID;
2675 }
2676
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002677 /* initiate structure */
Michal Vasko22df3f02020-08-24 13:29:22 +02002678 inout_p->nodetype = &((struct lysp_action *)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002679 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002680
2681 /* parse substatements */
Michal Vasko63f3d842020-07-08 10:10:14 +02002682 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002683 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002684 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002685 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci0f969882020-08-21 16:56:47 +02002686 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002687 case LY_STMT_ANYXML:
Michal Vasko22df3f02020-08-24 13:29:22 +02002688 LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node *)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002689 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002690 case LY_STMT_CHOICE:
Michal Vasko22df3f02020-08-24 13:29:22 +02002691 LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node *)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002692 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002693 case LY_STMT_CONTAINER:
Michal Vasko22df3f02020-08-24 13:29:22 +02002694 LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node *)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002695 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002696 case LY_STMT_LEAF:
Michal Vasko22df3f02020-08-24 13:29:22 +02002697 LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node *)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002698 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002699 case LY_STMT_LEAF_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02002700 LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node *)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002701 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002702 case LY_STMT_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02002703 LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node *)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002704 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002705 case LY_STMT_USES:
Michal Vasko22df3f02020-08-24 13:29:22 +02002706 LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node *)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002707 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002708 case LY_STMT_TYPEDEF:
Michal Vasko22df3f02020-08-24 13:29:22 +02002709 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)inout_p, in, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002710 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002711 case LY_STMT_MUST:
Radek Krejci335332a2019-09-05 13:03:35 +02002712 PARSER_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Michal Vasko63f3d842020-07-08 10:10:14 +02002713 LY_CHECK_RET(parse_restrs(ctx, in, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002714 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002715 case LY_STMT_GROUPING:
Michal Vasko22df3f02020-08-24 13:29:22 +02002716 LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node *)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002717 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002718 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002719 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002720 break;
2721 default:
David Sedlákb3077192019-06-19 10:55:37 +02002722 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002723 return LY_EVALID;
2724 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002725 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002726 LY_CHECK_RET(ret);
Michal Vaskob83af8a2020-01-06 09:49:22 +01002727
Radek Krejci7fc68292019-06-12 13:51:09 +02002728checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002729 /* finalize parent pointers to the reallocated items */
Michal Vaskob36053d2020-03-26 15:49:30 +01002730 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_p->groupings, NULL, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02002731
Michal Vaskob83af8a2020-01-06 09:49:22 +01002732 if (!inout_p->data) {
2733 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2734 return LY_EVALID;
2735 }
2736
Michal Vasko7fbc8162018-09-17 10:35:16 +02002737 return ret;
2738}
2739
Michal Vaskoea5abea2018-09-18 13:10:54 +02002740/**
2741 * @brief Parse the action statement.
2742 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002743 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002744 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002745 * @param[in,out] actions Actions to add to.
2746 *
2747 * @return LY_ERR values.
2748 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002749LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02002750parse_action(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002751{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002752 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002753 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002754 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002755 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002756 struct lysp_action *act;
2757
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002758 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002759
2760 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02002761 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02002762 INSERT_WORD_RET(ctx, buf, act->name, word, word_len);
Michal Vasko1bf09392020-03-27 12:38:10 +01002763 act->nodetype = parent ? LYS_ACTION : LYS_RPC;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002764 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002765
Michal Vasko63f3d842020-07-08 10:10:14 +02002766 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002767 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002768 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02002769 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002770 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002771 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02002772 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002773 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002774 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002775 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002776 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002777 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002778 LY_CHECK_RET(parse_status(ctx, in, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002779 break;
2780
Radek Krejcid6b76452019-09-03 17:03:03 +02002781 case LY_STMT_INPUT:
Michal Vasko22df3f02020-08-24 13:29:22 +02002782 LY_CHECK_RET(parse_inout(ctx, in, kw, (struct lysp_node *)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002783 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002784 case LY_STMT_OUTPUT:
Michal Vasko22df3f02020-08-24 13:29:22 +02002785 LY_CHECK_RET(parse_inout(ctx, in, kw, (struct lysp_node *)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002786 break;
2787
Radek Krejcid6b76452019-09-03 17:03:03 +02002788 case LY_STMT_TYPEDEF:
Michal Vasko22df3f02020-08-24 13:29:22 +02002789 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)act, in, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002791 case LY_STMT_GROUPING:
Michal Vasko22df3f02020-08-24 13:29:22 +02002792 LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node *)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002793 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002794 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002795 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 break;
2797 default:
David Sedlákb3077192019-06-19 10:55:37 +02002798 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002799 return LY_EVALID;
2800 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002801 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002802 LY_CHECK_RET(ret);
Michal Vasko7f45cf22020-10-01 12:49:44 +02002803
2804 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2805 if (!act->input.nodetype) {
2806 act->input.nodetype = LYS_INPUT;
2807 act->input.parent = (struct lysp_node *)act;
2808 }
2809 if (!act->output.nodetype) {
2810 act->output.nodetype = LYS_OUTPUT;
2811 act->output.parent = (struct lysp_node *)act;
2812 }
2813
Radek Krejci7fc68292019-06-12 13:51:09 +02002814checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002815 /* finalize parent pointers to the reallocated items */
Michal Vaskob36053d2020-03-26 15:49:30 +01002816 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02002817
Michal Vasko7fbc8162018-09-17 10:35:16 +02002818 return ret;
2819}
2820
Michal Vaskoea5abea2018-09-18 13:10:54 +02002821/**
2822 * @brief Parse the notification statement.
2823 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002824 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002825 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002826 * @param[in,out] notifs Notifications to add to.
2827 *
2828 * @return LY_ERR values.
2829 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002830LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02002831parse_notif(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002832{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002833 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002834 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002835 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002836 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002837 struct lysp_notif *notif;
2838
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002839 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002840
2841 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02002842 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02002843 INSERT_WORD_RET(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002844 notif->nodetype = LYS_NOTIF;
2845 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002846
Michal Vasko63f3d842020-07-08 10:10:14 +02002847 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002848 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002849 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02002850 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002851 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002852 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02002853 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002854 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002855 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002856 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002858 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002859 LY_CHECK_RET(parse_status(ctx, in, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860 break;
2861
Radek Krejcid6b76452019-09-03 17:03:03 +02002862 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002863 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci0f969882020-08-21 16:56:47 +02002864 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002865 case LY_STMT_ANYXML:
Michal Vasko22df3f02020-08-24 13:29:22 +02002866 LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node *)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002867 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002868 case LY_STMT_CHOICE:
Michal Vasko22df3f02020-08-24 13:29:22 +02002869 LY_CHECK_RET(parse_case(ctx, in, (struct lysp_node *)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002870 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002871 case LY_STMT_CONTAINER:
Michal Vasko22df3f02020-08-24 13:29:22 +02002872 LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node *)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002873 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002874 case LY_STMT_LEAF:
Michal Vasko22df3f02020-08-24 13:29:22 +02002875 LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node *)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002876 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002877 case LY_STMT_LEAF_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02002878 LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node *)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002879 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002880 case LY_STMT_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02002881 LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node *)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002882 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002883 case LY_STMT_USES:
Michal Vasko22df3f02020-08-24 13:29:22 +02002884 LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node *)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002885 break;
2886
Radek Krejcid6b76452019-09-03 17:03:03 +02002887 case LY_STMT_MUST:
Radek Krejci335332a2019-09-05 13:03:35 +02002888 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
Michal Vasko63f3d842020-07-08 10:10:14 +02002889 LY_CHECK_RET(parse_restrs(ctx, in, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002890 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002891 case LY_STMT_TYPEDEF:
Michal Vasko22df3f02020-08-24 13:29:22 +02002892 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)notif, in, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002893 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002894 case LY_STMT_GROUPING:
Michal Vasko22df3f02020-08-24 13:29:22 +02002895 LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node *)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002896 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002897 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002898 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002899 break;
2900 default:
David Sedlákb3077192019-06-19 10:55:37 +02002901 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002902 return LY_EVALID;
2903 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002904 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002905 LY_CHECK_RET(ret);
2906checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002907 /* finalize parent pointers to the reallocated items */
Michal Vaskob36053d2020-03-26 15:49:30 +01002908 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02002909
Michal Vasko7fbc8162018-09-17 10:35:16 +02002910 return ret;
2911}
2912
Michal Vaskoea5abea2018-09-18 13:10:54 +02002913/**
2914 * @brief Parse the grouping statement.
2915 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002916 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02002917 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002918 * @param[in,out] groupings Groupings to add to.
2919 *
2920 * @return LY_ERR values.
2921 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002922LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02002923parse_grouping(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002924{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002925 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002926 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002927 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002928 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002929 struct lysp_grp *grp;
2930
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002931 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002932
2933 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02002934 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02002935 INSERT_WORD_RET(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002936 grp->nodetype = LYS_GROUPING;
2937 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002938
Michal Vasko63f3d842020-07-08 10:10:14 +02002939 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002940 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002941 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02002942 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002943 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002944 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002945 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002946 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002947 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02002948 LY_CHECK_RET(parse_status(ctx, in, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002949 break;
2950
Radek Krejcid6b76452019-09-03 17:03:03 +02002951 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002952 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci0f969882020-08-21 16:56:47 +02002953 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002954 case LY_STMT_ANYXML:
Michal Vasko22df3f02020-08-24 13:29:22 +02002955 LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node *)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002956 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002957 case LY_STMT_CHOICE:
Michal Vasko22df3f02020-08-24 13:29:22 +02002958 LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node *)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002959 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002960 case LY_STMT_CONTAINER:
Michal Vasko22df3f02020-08-24 13:29:22 +02002961 LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node *)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002962 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002963 case LY_STMT_LEAF:
Michal Vasko22df3f02020-08-24 13:29:22 +02002964 LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node *)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002965 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002966 case LY_STMT_LEAF_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02002967 LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node *)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002968 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002969 case LY_STMT_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02002970 LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node *)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002971 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002972 case LY_STMT_USES:
Michal Vasko22df3f02020-08-24 13:29:22 +02002973 LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node *)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002974 break;
2975
Radek Krejcid6b76452019-09-03 17:03:03 +02002976 case LY_STMT_TYPEDEF:
Michal Vasko22df3f02020-08-24 13:29:22 +02002977 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)grp, in, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002979 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02002980 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Michal Vasko22df3f02020-08-24 13:29:22 +02002981 LY_CHECK_RET(parse_action(ctx, in, (struct lysp_node *)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002982 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002983 case LY_STMT_GROUPING:
Michal Vasko22df3f02020-08-24 13:29:22 +02002984 LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node *)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002985 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002986 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02002987 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Michal Vasko22df3f02020-08-24 13:29:22 +02002988 LY_CHECK_RET(parse_notif(ctx, in, (struct lysp_node *)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002989 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002990 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02002991 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002992 break;
2993 default:
David Sedlákb3077192019-06-19 10:55:37 +02002994 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002995 return LY_EVALID;
2996 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002997 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002998 LY_CHECK_RET(ret);
2999checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003000 /* finalize parent pointers to the reallocated items */
Michal Vaskob36053d2020-03-26 15:49:30 +01003001 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
Radek Krejci7fc68292019-06-12 13:51:09 +02003002
Michal Vasko7fbc8162018-09-17 10:35:16 +02003003 return ret;
3004}
3005
Michal Vaskoea5abea2018-09-18 13:10:54 +02003006/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02003007 * @brief Parse the augment statement.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003008 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003009 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003010 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003011 * @param[in,out] augments Augments to add to.
3012 *
3013 * @return LY_ERR values.
3014 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003015LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003016parse_augment(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003017{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003018 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003019 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003020 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003021 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003022 struct lysp_augment *aug;
3023
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003024 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003025
3026 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02003027 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vaskob36053d2020-03-26 15:49:30 +01003028 CHECK_NONEMPTY(ctx, word_len, "augment");
Radek Krejci011e4aa2020-09-04 15:22:31 +02003029 INSERT_WORD_RET(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003030 aug->nodetype = LYS_AUGMENT;
3031 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032
Michal Vasko63f3d842020-07-08 10:10:14 +02003033 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003034 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003035 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02003036 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003037 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003038 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003039 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003040 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003041 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003042 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003043 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003044 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02003045 LY_CHECK_RET(parse_status(ctx, in, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003046 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003047 case LY_STMT_WHEN:
Michal Vasko63f3d842020-07-08 10:10:14 +02003048 LY_CHECK_RET(parse_when(ctx, in, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003049 break;
3050
Radek Krejcid6b76452019-09-03 17:03:03 +02003051 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003052 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci0f969882020-08-21 16:56:47 +02003053 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003054 case LY_STMT_ANYXML:
Michal Vasko22df3f02020-08-24 13:29:22 +02003055 LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003056 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003057 case LY_STMT_CASE:
Michal Vasko22df3f02020-08-24 13:29:22 +02003058 LY_CHECK_RET(parse_case(ctx, in, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003059 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003060 case LY_STMT_CHOICE:
Michal Vasko22df3f02020-08-24 13:29:22 +02003061 LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003062 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003063 case LY_STMT_CONTAINER:
Michal Vasko22df3f02020-08-24 13:29:22 +02003064 LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003065 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003066 case LY_STMT_LEAF:
Michal Vasko22df3f02020-08-24 13:29:22 +02003067 LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003068 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003069 case LY_STMT_LEAF_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02003070 LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003071 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003072 case LY_STMT_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02003073 LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003074 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003075 case LY_STMT_USES:
Michal Vasko22df3f02020-08-24 13:29:22 +02003076 LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node *)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003077 break;
3078
Radek Krejcid6b76452019-09-03 17:03:03 +02003079 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02003080 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
Michal Vasko22df3f02020-08-24 13:29:22 +02003081 LY_CHECK_RET(parse_action(ctx, in, (struct lysp_node *)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003082 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003083 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02003084 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Michal Vasko22df3f02020-08-24 13:29:22 +02003085 LY_CHECK_RET(parse_notif(ctx, in, (struct lysp_node *)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003086 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003087 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003088 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003089 break;
3090 default:
David Sedlákb3077192019-06-19 10:55:37 +02003091 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003092 return LY_EVALID;
3093 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003094 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003095 LY_CHECK_RET(ret);
3096checks:
3097 /* finalize parent pointers to the reallocated items */
Michal Vaskob36053d2020-03-26 15:49:30 +01003098 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
Radek Krejci7fc68292019-06-12 13:51:09 +02003099
Michal Vasko7fbc8162018-09-17 10:35:16 +02003100 return ret;
3101}
3102
Michal Vaskoea5abea2018-09-18 13:10:54 +02003103/**
3104 * @brief Parse the uses statement.
3105 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003106 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003107 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003108 * @param[in,out] siblings Siblings to add to.
3109 *
3110 * @return LY_ERR values.
3111 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003112LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003113parse_uses(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003114{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003115 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003116 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003117 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003118 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003119 struct lysp_node_uses *uses;
3120
David Sedlák60adc092019-08-06 15:57:02 +02003121 /* create uses structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003122 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, uses, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003123 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003124 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003125
Michal Vasko7fbc8162018-09-17 10:35:16 +02003126 /* get name */
Michal Vasko63f3d842020-07-08 10:10:14 +02003127 LY_CHECK_RET(get_argument(ctx, in, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02003128 INSERT_WORD_RET(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003129
3130 /* parse substatements */
Michal Vasko63f3d842020-07-08 10:10:14 +02003131 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003132 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003133 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02003134 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003136 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003137 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003138 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003139 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003140 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003141 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003142 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02003143 LY_CHECK_RET(parse_status(ctx, in, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003144 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003145 case LY_STMT_WHEN:
Michal Vasko63f3d842020-07-08 10:10:14 +02003146 LY_CHECK_RET(parse_when(ctx, in, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003147 break;
3148
Radek Krejcid6b76452019-09-03 17:03:03 +02003149 case LY_STMT_REFINE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003150 LY_CHECK_RET(parse_refine(ctx, in, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003151 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003152 case LY_STMT_AUGMENT:
Michal Vasko22df3f02020-08-24 13:29:22 +02003153 LY_CHECK_RET(parse_augment(ctx, in, (struct lysp_node *)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003154 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003155 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003156 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003157 break;
3158 default:
David Sedlákb3077192019-06-19 10:55:37 +02003159 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003160 return LY_EVALID;
3161 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003162 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003163checks:
3164 /* finalize parent pointers to the reallocated items */
Michal Vaskob36053d2020-03-26 15:49:30 +01003165 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02003166
Michal Vasko7fbc8162018-09-17 10:35:16 +02003167 return ret;
3168}
3169
Michal Vaskoea5abea2018-09-18 13:10:54 +02003170/**
3171 * @brief Parse the case statement.
3172 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003173 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003174 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003175 * @param[in,out] siblings Siblings to add to.
3176 *
3177 * @return LY_ERR values.
3178 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003179LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003180parse_case(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003181{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003182 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003183 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003184 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003185 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003186 struct lysp_node_case *cas;
3187
David Sedlák60adc092019-08-06 15:57:02 +02003188 /* create new case structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003189 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cas, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003190 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003191 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003192
Michal Vasko7fbc8162018-09-17 10:35:16 +02003193 /* get name */
Michal Vasko63f3d842020-07-08 10:10:14 +02003194 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02003195 INSERT_WORD_RET(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003196
3197 /* parse substatements */
Michal Vaskod989ba02020-08-24 10:59:24 +02003198 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003199 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003200 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02003201 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003202 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003203 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003204 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003205 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003206 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003207 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003208 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003209 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02003210 LY_CHECK_RET(parse_status(ctx, in, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003211 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003212 case LY_STMT_WHEN:
Michal Vasko63f3d842020-07-08 10:10:14 +02003213 LY_CHECK_RET(parse_when(ctx, in, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003214 break;
3215
Radek Krejcid6b76452019-09-03 17:03:03 +02003216 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003217 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci0f969882020-08-21 16:56:47 +02003218 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003219 case LY_STMT_ANYXML:
Michal Vasko22df3f02020-08-24 13:29:22 +02003220 LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003221 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003222 case LY_STMT_CHOICE:
Michal Vasko22df3f02020-08-24 13:29:22 +02003223 LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003225 case LY_STMT_CONTAINER:
Michal Vasko22df3f02020-08-24 13:29:22 +02003226 LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003227 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003228 case LY_STMT_LEAF:
Michal Vasko22df3f02020-08-24 13:29:22 +02003229 LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003230 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003231 case LY_STMT_LEAF_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02003232 LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003233 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003234 case LY_STMT_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02003235 LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003236 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003237 case LY_STMT_USES:
Michal Vasko22df3f02020-08-24 13:29:22 +02003238 LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node *)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003239 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003240 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003241 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003242 break;
3243 default:
David Sedlákb3077192019-06-19 10:55:37 +02003244 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003245 return LY_EVALID;
3246 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003247 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003248 return ret;
3249}
3250
Michal Vaskoea5abea2018-09-18 13:10:54 +02003251/**
3252 * @brief Parse the choice statement.
3253 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003254 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003255 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003256 * @param[in,out] siblings Siblings to add to.
3257 *
3258 * @return LY_ERR values.
3259 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003260LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003261parse_choice(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003262{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003263 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003264 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003265 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003266 enum ly_stmt kw;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003267 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003268
David Sedlák60adc092019-08-06 15:57:02 +02003269 /* create new choice structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003270 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, choice, next, LY_EMEM);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003271 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003272 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003273
Michal Vasko7fbc8162018-09-17 10:35:16 +02003274 /* get name */
Michal Vasko63f3d842020-07-08 10:10:14 +02003275 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02003276 INSERT_WORD_RET(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003277
3278 /* parse substatements */
Michal Vasko7f45cf22020-10-01 12:49:44 +02003279 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003280 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003281 case LY_STMT_CONFIG:
Michal Vasko63f3d842020-07-08 10:10:14 +02003282 LY_CHECK_RET(parse_config(ctx, in, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003283 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003284 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02003285 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003286 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003287 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003288 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003289 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003290 case LY_STMT_MANDATORY:
Michal Vasko63f3d842020-07-08 10:10:14 +02003291 LY_CHECK_RET(parse_mandatory(ctx, in, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003292 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003293 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003294 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003295 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003296 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02003297 LY_CHECK_RET(parse_status(ctx, in, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003298 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003299 case LY_STMT_WHEN:
Michal Vasko63f3d842020-07-08 10:10:14 +02003300 LY_CHECK_RET(parse_when(ctx, in, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003301 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003302 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003303 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt.str, Y_PREF_IDENTIF_ARG,
3304 &choice->exts));
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003305 choice->dflt.mod = ctx->parsed_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003306 break;
3307
Radek Krejcid6b76452019-09-03 17:03:03 +02003308 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003309 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci0f969882020-08-21 16:56:47 +02003310 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003311 case LY_STMT_ANYXML:
Michal Vasko22df3f02020-08-24 13:29:22 +02003312 LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003313 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003314 case LY_STMT_CASE:
Michal Vasko22df3f02020-08-24 13:29:22 +02003315 LY_CHECK_RET(parse_case(ctx, in, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003316 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003317 case LY_STMT_CHOICE:
Radek Krejci335332a2019-09-05 13:03:35 +02003318 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Michal Vasko22df3f02020-08-24 13:29:22 +02003319 LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003320 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003321 case LY_STMT_CONTAINER:
Michal Vasko22df3f02020-08-24 13:29:22 +02003322 LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003323 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003324 case LY_STMT_LEAF:
Michal Vasko22df3f02020-08-24 13:29:22 +02003325 LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003326 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003327 case LY_STMT_LEAF_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02003328 LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003329 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003330 case LY_STMT_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02003331 LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node *)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003332 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003333 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003334 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003335 break;
3336 default:
David Sedlákb3077192019-06-19 10:55:37 +02003337 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003338 return LY_EVALID;
3339 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003340 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003341 return ret;
3342}
3343
Michal Vaskoea5abea2018-09-18 13:10:54 +02003344/**
3345 * @brief Parse the container statement.
3346 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003347 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003348 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003349 * @param[in,out] siblings Siblings to add to.
3350 *
3351 * @return LY_ERR values.
3352 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003353LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003354parse_container(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003355{
3356 LY_ERR ret = 0;
3357 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003358 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003359 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003360 struct lysp_node_container *cont;
3361
David Sedlák60adc092019-08-06 15:57:02 +02003362 /* create new container structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003363 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, cont, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003364 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003365 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003366
Michal Vasko7fbc8162018-09-17 10:35:16 +02003367 /* get name */
Michal Vasko63f3d842020-07-08 10:10:14 +02003368 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02003369 INSERT_WORD_RET(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003370
3371 /* parse substatements */
Michal Vasko63f3d842020-07-08 10:10:14 +02003372 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003373 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003374 case LY_STMT_CONFIG:
Michal Vasko63f3d842020-07-08 10:10:14 +02003375 LY_CHECK_RET(parse_config(ctx, in, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003376 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003377 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02003378 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003379 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003380 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003381 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003382 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003383 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003384 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003385 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003386 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02003387 LY_CHECK_RET(parse_status(ctx, in, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003388 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003389 case LY_STMT_WHEN:
Michal Vasko63f3d842020-07-08 10:10:14 +02003390 LY_CHECK_RET(parse_when(ctx, in, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003391 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003392 case LY_STMT_PRESENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003393 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003394 break;
3395
Radek Krejcid6b76452019-09-03 17:03:03 +02003396 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003397 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci0f969882020-08-21 16:56:47 +02003398 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003399 case LY_STMT_ANYXML:
Michal Vasko22df3f02020-08-24 13:29:22 +02003400 LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003401 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003402 case LY_STMT_CHOICE:
Michal Vasko22df3f02020-08-24 13:29:22 +02003403 LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003404 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003405 case LY_STMT_CONTAINER:
Michal Vasko22df3f02020-08-24 13:29:22 +02003406 LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003407 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003408 case LY_STMT_LEAF:
Michal Vasko22df3f02020-08-24 13:29:22 +02003409 LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003410 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003411 case LY_STMT_LEAF_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02003412 LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003413 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003414 case LY_STMT_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02003415 LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003416 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003417 case LY_STMT_USES:
Michal Vasko22df3f02020-08-24 13:29:22 +02003418 LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node *)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003419 break;
3420
Radek Krejcid6b76452019-09-03 17:03:03 +02003421 case LY_STMT_TYPEDEF:
Michal Vasko22df3f02020-08-24 13:29:22 +02003422 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)cont, in, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003423 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003424 case LY_STMT_MUST:
Michal Vasko63f3d842020-07-08 10:10:14 +02003425 LY_CHECK_RET(parse_restrs(ctx, in, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003426 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003427 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02003428 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
Michal Vasko22df3f02020-08-24 13:29:22 +02003429 LY_CHECK_RET(parse_action(ctx, in, (struct lysp_node *)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003430 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003431 case LY_STMT_GROUPING:
Michal Vasko22df3f02020-08-24 13:29:22 +02003432 LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node *)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003433 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003434 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02003435 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
Michal Vasko22df3f02020-08-24 13:29:22 +02003436 LY_CHECK_RET(parse_notif(ctx, in, (struct lysp_node *)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003437 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003438 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003439 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003440 break;
3441 default:
David Sedlákb3077192019-06-19 10:55:37 +02003442 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003443 return LY_EVALID;
3444 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003445 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003446checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003447 /* finalize parent pointers to the reallocated items */
Michal Vaskob36053d2020-03-26 15:49:30 +01003448 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003449 return ret;
3450}
3451
Michal Vaskoea5abea2018-09-18 13:10:54 +02003452/**
3453 * @brief Parse the list statement.
3454 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003455 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003456 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003457 * @param[in,out] siblings Siblings to add to.
3458 *
3459 * @return LY_ERR values.
3460 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003461LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003462parse_list(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003463{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003464 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003465 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003466 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003467 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003468 struct lysp_node_list *list;
3469
David Sedlák60adc092019-08-06 15:57:02 +02003470 /* create new list structure */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003471 LY_LIST_NEW_RET(PARSER_CTX(ctx), siblings, list, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003472 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003473 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003474
Michal Vasko7fbc8162018-09-17 10:35:16 +02003475 /* get name */
Michal Vasko63f3d842020-07-08 10:10:14 +02003476 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02003477 INSERT_WORD_RET(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003478
3479 /* parse substatements */
Michal Vasko63f3d842020-07-08 10:10:14 +02003480 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003481 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003482 case LY_STMT_CONFIG:
Michal Vasko63f3d842020-07-08 10:10:14 +02003483 LY_CHECK_RET(parse_config(ctx, in, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003484 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003485 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02003486 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003487 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003488 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003489 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003490 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003491 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003492 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003493 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003494 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02003495 LY_CHECK_RET(parse_status(ctx, in, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003496 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003497 case LY_STMT_WHEN:
Michal Vasko63f3d842020-07-08 10:10:14 +02003498 LY_CHECK_RET(parse_when(ctx, in, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003499 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003500 case LY_STMT_KEY:
Michal Vasko63f3d842020-07-08 10:10:14 +02003501 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003502 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003503 case LY_STMT_MAX_ELEMENTS:
Michal Vasko63f3d842020-07-08 10:10:14 +02003504 LY_CHECK_RET(parse_maxelements(ctx, in, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003505 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003506 case LY_STMT_MIN_ELEMENTS:
Michal Vasko63f3d842020-07-08 10:10:14 +02003507 LY_CHECK_RET(parse_minelements(ctx, in, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003508 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003509 case LY_STMT_ORDERED_BY:
Michal Vasko63f3d842020-07-08 10:10:14 +02003510 LY_CHECK_RET(parse_orderedby(ctx, in, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003511 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003512 case LY_STMT_UNIQUE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003513 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003514 break;
3515
Radek Krejcid6b76452019-09-03 17:03:03 +02003516 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003517 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci0f969882020-08-21 16:56:47 +02003518 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003519 case LY_STMT_ANYXML:
Michal Vasko22df3f02020-08-24 13:29:22 +02003520 LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003521 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003522 case LY_STMT_CHOICE:
Michal Vasko22df3f02020-08-24 13:29:22 +02003523 LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003524 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003525 case LY_STMT_CONTAINER:
Michal Vasko22df3f02020-08-24 13:29:22 +02003526 LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003527 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003528 case LY_STMT_LEAF:
Michal Vasko22df3f02020-08-24 13:29:22 +02003529 LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003531 case LY_STMT_LEAF_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02003532 LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003533 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003534 case LY_STMT_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02003535 LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003536 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003537 case LY_STMT_USES:
Michal Vasko22df3f02020-08-24 13:29:22 +02003538 LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node *)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003539 break;
3540
Radek Krejcid6b76452019-09-03 17:03:03 +02003541 case LY_STMT_TYPEDEF:
Michal Vasko22df3f02020-08-24 13:29:22 +02003542 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node *)list, in, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003544 case LY_STMT_MUST:
Michal Vasko63f3d842020-07-08 10:10:14 +02003545 LY_CHECK_RET(parse_restrs(ctx, in, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003546 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003547 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02003548 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
Michal Vasko22df3f02020-08-24 13:29:22 +02003549 LY_CHECK_RET(parse_action(ctx, in, (struct lysp_node *)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003550 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003551 case LY_STMT_GROUPING:
Michal Vasko22df3f02020-08-24 13:29:22 +02003552 LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node *)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003553 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003554 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02003555 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
Michal Vasko22df3f02020-08-24 13:29:22 +02003556 LY_CHECK_RET(parse_notif(ctx, in, (struct lysp_node *)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003557 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003558 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003559 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003560 break;
3561 default:
David Sedlákb3077192019-06-19 10:55:37 +02003562 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003563 return LY_EVALID;
3564 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003565 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003566 LY_CHECK_RET(ret);
3567checks:
Radek Krejci7fc68292019-06-12 13:51:09 +02003568 /* finalize parent pointers to the reallocated items */
Michal Vaskob36053d2020-03-26 15:49:30 +01003569 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
Radek Krejci7fc68292019-06-12 13:51:09 +02003570
Michal Vasko7fbc8162018-09-17 10:35:16 +02003571 return ret;
3572}
3573
Michal Vaskoea5abea2018-09-18 13:10:54 +02003574/**
3575 * @brief Parse the yin-element statement.
3576 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003577 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003578 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003579 * @param[in,out] flags Flags to write to.
3580 * @param[in,out] exts Extension instances to add to.
3581 *
3582 * @return LY_ERR values.
3583 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003585parse_yinelement(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003586{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003587 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003588 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003589 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003590 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003591
3592 if (*flags & LYS_YINELEM_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02003593 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003594 return LY_EVALID;
3595 }
3596
3597 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02003598 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003599
Radek Krejcif13b87b2020-12-01 22:02:17 +01003600 if ((word_len == ly_strlen_const("true")) && !strncmp(word, "true", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003601 *flags |= LYS_YINELEM_TRUE;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003602 } else if ((word_len == ly_strlen_const("false")) && !strncmp(word, "false", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003603 *flags |= LYS_YINELEM_FALSE;
3604 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003605 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003606 free(buf);
3607 return LY_EVALID;
3608 }
3609 free(buf);
3610
Michal Vaskod989ba02020-08-24 10:59:24 +02003611 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003612 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003613 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003614 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
Michal Vaskod989ba02020-08-24 10:59:24 +02003615 LY_CHECK_RET(ret);
3616 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003617 default:
David Sedlákb3077192019-06-19 10:55:37 +02003618 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003619 return LY_EVALID;
3620 }
3621 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003622 return ret;
3623}
3624
Michal Vaskoea5abea2018-09-18 13:10:54 +02003625/**
David Sedlák2444f8f2019-07-09 11:02:47 +02003626 * @brief Parse the argument statement.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003627 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003628 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003629 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003630 * @param[in,out] argument Value to write to.
3631 * @param[in,out] flags Flags to write to.
3632 * @param[in,out] exts Extension instances to add to.
3633 *
3634 * @return LY_ERR values.
3635 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003636static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003637parse_argument(struct lys_yang_parser_ctx *ctx, struct ly_in *in, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003638{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003639 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003640 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003641 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003642 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643
3644 if (*argument) {
David Sedlákb3077192019-06-19 10:55:37 +02003645 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003646 return LY_EVALID;
3647 }
3648
3649 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02003650 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02003651 INSERT_WORD_RET(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003652
Michal Vaskod989ba02020-08-24 10:59:24 +02003653 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003654 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003655 case LY_STMT_YIN_ELEMENT:
Michal Vasko63f3d842020-07-08 10:10:14 +02003656 LY_CHECK_RET(parse_yinelement(ctx, in, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003657 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003658 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003659 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003660 break;
3661 default:
David Sedlákb3077192019-06-19 10:55:37 +02003662 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003663 return LY_EVALID;
3664 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003665 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003666 return ret;
3667}
3668
Michal Vaskoea5abea2018-09-18 13:10:54 +02003669/**
3670 * @brief Parse the extension statement.
3671 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003672 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003673 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003674 * @param[in,out] extensions Extensions to add to.
3675 *
3676 * @return LY_ERR values.
3677 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003678static LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003679parse_extension(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003680{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003681 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003682 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003683 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003684 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003685 struct lysp_ext *ex;
3686
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003687 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003688
3689 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02003690 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02003691 INSERT_WORD_RET(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003692
Michal Vaskod989ba02020-08-24 10:59:24 +02003693 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003694 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003695 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02003696 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003697 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003698 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003699 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003700 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003701 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02003702 LY_CHECK_RET(parse_status(ctx, in, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003703 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003704 case LY_STMT_ARGUMENT:
Michal Vasko63f3d842020-07-08 10:10:14 +02003705 LY_CHECK_RET(parse_argument(ctx, in, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003706 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003707 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003708 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003709 break;
3710 default:
David Sedlákb3077192019-06-19 10:55:37 +02003711 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003712 return LY_EVALID;
3713 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003714 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003715 return ret;
3716}
3717
Michal Vaskoea5abea2018-09-18 13:10:54 +02003718/**
3719 * @brief Parse the deviate statement.
3720 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003721 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003722 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003723 * @param[in,out] deviates Deviates to add to.
3724 *
3725 * @return LY_ERR values.
3726 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003727LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003728parse_deviate(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003729{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003730 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003731 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003732 size_t word_len, dev_mod;
Radek Krejcid6b76452019-09-03 17:03:03 +02003733 enum ly_stmt kw;
David Sedlák60adc092019-08-06 15:57:02 +02003734 struct lysp_deviate *d;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003735 struct lysp_deviate_add *d_add = NULL;
3736 struct lysp_deviate_rpl *d_rpl = NULL;
3737 struct lysp_deviate_del *d_del = NULL;
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003738 const char **d_units = NULL;
3739 struct lysp_qname **d_uniques = NULL, **d_dflts = NULL;
Radek Krejci4ad42aa2019-07-23 16:55:58 +02003740 struct lysp_restr **d_musts = NULL;
3741 uint16_t *d_flags = 0;
3742 uint32_t *d_min = 0, *d_max = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003743
3744 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02003745 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003746
Radek Krejcif13b87b2020-12-01 22:02:17 +01003747 if ((word_len == ly_strlen_const("not-supported")) && !strncmp(word, "not-supported", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003748 dev_mod = LYS_DEV_NOT_SUPPORTED;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003749 } else if ((word_len == ly_strlen_const("add")) && !strncmp(word, "add", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003750 dev_mod = LYS_DEV_ADD;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003751 } else if ((word_len == ly_strlen_const("replace")) && !strncmp(word, "replace", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003752 dev_mod = LYS_DEV_REPLACE;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003753 } else if ((word_len == ly_strlen_const("delete")) && !strncmp(word, "delete", word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003754 dev_mod = LYS_DEV_DELETE;
3755 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003756 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003757 free(buf);
3758 return LY_EVALID;
3759 }
3760 free(buf);
3761
3762 /* create structure */
3763 switch (dev_mod) {
3764 case LYS_DEV_NOT_SUPPORTED:
3765 d = calloc(1, sizeof *d);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003766 LY_CHECK_ERR_RET(!d, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003767 break;
3768 case LYS_DEV_ADD:
3769 d_add = calloc(1, sizeof *d_add);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003770 LY_CHECK_ERR_RET(!d_add, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003771 d = (struct lysp_deviate *)d_add;
3772 d_units = &d_add->units;
3773 d_uniques = &d_add->uniques;
3774 d_dflts = &d_add->dflts;
3775 d_musts = &d_add->musts;
3776 d_flags = &d_add->flags;
3777 d_min = &d_add->min;
3778 d_max = &d_add->max;
3779 break;
3780 case LYS_DEV_REPLACE:
3781 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003782 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003783 d = (struct lysp_deviate *)d_rpl;
3784 d_units = &d_rpl->units;
3785 d_flags = &d_rpl->flags;
3786 d_min = &d_rpl->min;
3787 d_max = &d_rpl->max;
3788 break;
3789 case LYS_DEV_DELETE:
3790 d_del = calloc(1, sizeof *d_del);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003791 LY_CHECK_ERR_RET(!d_del, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003792 d = (struct lysp_deviate *)d_del;
3793 d_units = &d_del->units;
3794 d_uniques = &d_del->uniques;
3795 d_dflts = &d_del->dflts;
3796 d_musts = &d_del->musts;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003797 break;
3798 default:
3799 assert(0);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003800 LOGINT_RET(PARSER_CTX(ctx));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003801 }
3802 d->mod = dev_mod;
3803
3804 /* insert into siblings */
David Sedlák60adc092019-08-06 15:57:02 +02003805 LY_LIST_INSERT(deviates, d, next);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003806
Michal Vaskod989ba02020-08-24 10:59:24 +02003807 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003808 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003809 case LY_STMT_CONFIG:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003810 switch (dev_mod) {
3811 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003812 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003813 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003814 return LY_EVALID;
3815 default:
Michal Vasko63f3d842020-07-08 10:10:14 +02003816 LY_CHECK_RET(parse_config(ctx, in, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003817 break;
3818 }
3819 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003820 case LY_STMT_DEFAULT:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003821 switch (dev_mod) {
3822 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02003823 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003824 return LY_EVALID;
3825 case LYS_DEV_REPLACE:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003826 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt.str, Y_STR_ARG, &d->exts));
3827 d_rpl->dflt.mod = ctx->parsed_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003828 break;
3829 default:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003830 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003831 break;
3832 }
3833 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003834 case LY_STMT_MANDATORY:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003835 switch (dev_mod) {
3836 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003837 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003838 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003839 return LY_EVALID;
3840 default:
Michal Vasko63f3d842020-07-08 10:10:14 +02003841 LY_CHECK_RET(parse_mandatory(ctx, in, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003842 break;
3843 }
3844 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003845 case LY_STMT_MAX_ELEMENTS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003846 switch (dev_mod) {
3847 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003848 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003849 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003850 return LY_EVALID;
3851 default:
Michal Vasko63f3d842020-07-08 10:10:14 +02003852 LY_CHECK_RET(parse_maxelements(ctx, in, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003853 break;
3854 }
3855 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003856 case LY_STMT_MIN_ELEMENTS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003857 switch (dev_mod) {
3858 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003859 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003860 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003861 return LY_EVALID;
3862 default:
Michal Vasko63f3d842020-07-08 10:10:14 +02003863 LY_CHECK_RET(parse_minelements(ctx, in, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003864 break;
3865 }
3866 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003867 case LY_STMT_MUST:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003868 switch (dev_mod) {
3869 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003870 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02003871 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003872 return LY_EVALID;
3873 default:
Michal Vasko63f3d842020-07-08 10:10:14 +02003874 LY_CHECK_RET(parse_restrs(ctx, in, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003875 break;
3876 }
3877 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003878 case LY_STMT_TYPE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003879 switch (dev_mod) {
3880 case LYS_DEV_NOT_SUPPORTED:
3881 case LYS_DEV_ADD:
3882 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003883 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003884 return LY_EVALID;
3885 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003886 if (d_rpl->type) {
David Sedlákb3077192019-06-19 10:55:37 +02003887 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003888 return LY_EVALID;
3889 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003890 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003891 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(PARSER_CTX(ctx)), LY_EMEM);
Michal Vasko63f3d842020-07-08 10:10:14 +02003892 LY_CHECK_RET(parse_type(ctx, in, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003893 break;
3894 }
3895 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003896 case LY_STMT_UNIQUE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003897 switch (dev_mod) {
3898 case LYS_DEV_NOT_SUPPORTED:
3899 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02003900 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003901 return LY_EVALID;
3902 default:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003903 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003904 break;
3905 }
3906 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003907 case LY_STMT_UNITS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003908 switch (dev_mod) {
3909 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02003910 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003911 return LY_EVALID;
3912 default:
Michal Vasko63f3d842020-07-08 10:10:14 +02003913 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003914 break;
3915 }
3916 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003917 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003918 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003919 break;
3920 default:
David Sedlákb3077192019-06-19 10:55:37 +02003921 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 return LY_EVALID;
3923 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003924 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003925 return ret;
3926}
3927
Michal Vaskoea5abea2018-09-18 13:10:54 +02003928/**
3929 * @brief Parse the deviation statement.
3930 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003931 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003932 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003933 * @param[in,out] deviations Deviations to add to.
3934 *
3935 * @return LY_ERR values.
3936 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003937LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003938parse_deviation(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003939{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003940 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003941 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003942 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003943 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003944 struct lysp_deviation *dev;
3945
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003946 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003947
3948 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02003949 LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vaskob36053d2020-03-26 15:49:30 +01003950 CHECK_NONEMPTY(ctx, word_len, "deviation");
Radek Krejci011e4aa2020-09-04 15:22:31 +02003951 INSERT_WORD_RET(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003952
Michal Vasko63f3d842020-07-08 10:10:14 +02003953 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003954 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003955 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02003956 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003957 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003958 case LY_STMT_DEVIATE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003959 LY_CHECK_RET(parse_deviate(ctx, in, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003960 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003961 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003962 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003963 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003964 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02003965 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003966 break;
3967 default:
David Sedlákb3077192019-06-19 10:55:37 +02003968 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003969 return LY_EVALID;
3970 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003971 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003972 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01003973checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003974 /* mandatory substatements */
3975 if (!dev->deviates) {
David Sedlákb3077192019-06-19 10:55:37 +02003976 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003977 return LY_EVALID;
3978 }
3979
3980 return ret;
3981}
3982
Michal Vaskoea5abea2018-09-18 13:10:54 +02003983/**
3984 * @brief Parse the feature statement.
3985 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003986 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02003987 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003988 * @param[in,out] features Features to add to.
3989 *
3990 * @return LY_ERR values.
3991 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003992LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003993parse_feature(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003994{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003995 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003996 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003997 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003998 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003999 struct lysp_feature *feat;
4000
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004001 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004002
4003 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02004004 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02004005 INSERT_WORD_RET(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004006
Michal Vaskod989ba02020-08-24 10:59:24 +02004007 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004008 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02004009 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004010 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004011 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004012 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02004013 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004014 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004015 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004016 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004018 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02004019 LY_CHECK_RET(parse_status(ctx, in, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004020 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004021 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004022 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004023 break;
4024 default:
David Sedlákb3077192019-06-19 10:55:37 +02004025 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004026 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004027 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004028 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004029 return ret;
4030}
4031
Michal Vaskoea5abea2018-09-18 13:10:54 +02004032/**
4033 * @brief Parse the identity statement.
4034 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004035 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02004036 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004037 * @param[in,out] identities Identities to add to.
4038 *
4039 * @return LY_ERR values.
4040 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004041LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02004042parse_identity(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004043{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004044 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004045 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004046 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004047 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004048 struct lysp_ident *ident;
4049
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004050 LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004051
4052 /* get value */
Michal Vasko63f3d842020-07-08 10:10:14 +02004053 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02004054 INSERT_WORD_RET(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004055
Michal Vaskod989ba02020-08-24 10:59:24 +02004056 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, ) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004057 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02004058 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004059 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004060 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004061 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02004062 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Michal Vasko7f45cf22020-10-01 12:49:44 +02004063 LY_CHECK_RET(parse_qnames(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004064 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004065 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004066 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004067 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004068 case LY_STMT_STATUS:
Michal Vasko63f3d842020-07-08 10:10:14 +02004069 LY_CHECK_RET(parse_status(ctx, in, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004070 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004071 case LY_STMT_BASE:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004072 if (ident->bases && (ctx->parsed_mod->version < LYS_VERSION_1_1)) {
David Sedlákb3077192019-06-19 10:55:37 +02004073 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 +01004074 return LY_EVALID;
4075 }
Michal Vasko63f3d842020-07-08 10:10:14 +02004076 LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004077 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004078 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004079 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004080 break;
4081 default:
David Sedlákb3077192019-06-19 10:55:37 +02004082 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004083 return LY_EVALID;
4084 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004085 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004086 return ret;
4087}
4088
Michal Vaskoea5abea2018-09-18 13:10:54 +02004089/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004090 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004091 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004092 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02004093 * @param[in,out] in Input structure.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004094 * @param[in,out] mod Module to write to.
4095 *
4096 * @return LY_ERR values.
4097 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004098LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02004099parse_module(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004100{
4101 LY_ERR ret = 0;
4102 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004103 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004104 enum ly_stmt kw, prev_kw = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004105 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004106 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004107
Michal Vaskoc3781c32020-10-06 14:04:08 +02004108 mod->is_submod = 0;
4109
4110 /* module name */
Michal Vasko63f3d842020-07-08 10:10:14 +02004111 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02004112 INSERT_WORD_RET(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004113
Michal Vasko63f3d842020-07-08 10:10:14 +02004114 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004115
Radek Krejcie3846472018-10-15 15:24:51 +02004116#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004117 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 +02004118
Michal Vasko7fbc8162018-09-17 10:35:16 +02004119 switch (kw) {
4120 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004121 case LY_STMT_NAMESPACE:
4122 case LY_STMT_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004123 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4124 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004125 case LY_STMT_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004126 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004127 break;
4128 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004129 case LY_STMT_INCLUDE:
4130 case LY_STMT_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004131 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004132 break;
4133 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004134 case LY_STMT_ORGANIZATION:
4135 case LY_STMT_CONTACT:
4136 case LY_STMT_DESCRIPTION:
4137 case LY_STMT_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004138 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004139 break;
4140
4141 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004142 case LY_STMT_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004143 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004144 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004145 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004146 case LY_STMT_ANYDATA:
4147 case LY_STMT_ANYXML:
4148 case LY_STMT_AUGMENT:
4149 case LY_STMT_CHOICE:
4150 case LY_STMT_CONTAINER:
4151 case LY_STMT_DEVIATION:
4152 case LY_STMT_EXTENSION:
4153 case LY_STMT_FEATURE:
4154 case LY_STMT_GROUPING:
4155 case LY_STMT_IDENTITY:
4156 case LY_STMT_LEAF:
4157 case LY_STMT_LEAF_LIST:
4158 case LY_STMT_LIST:
4159 case LY_STMT_NOTIFICATION:
4160 case LY_STMT_RPC:
4161 case LY_STMT_TYPEDEF:
4162 case LY_STMT_USES:
4163 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004164 mod_stmt = Y_MOD_BODY;
4165 break;
4166 default:
4167 /* error handled in the next switch */
4168 break;
4169 }
Radek Krejcie3846472018-10-15 15:24:51 +02004170#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004171
Radek Krejcie3846472018-10-15 15:24:51 +02004172 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004173 switch (kw) {
4174 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004175 case LY_STMT_YANG_VERSION:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004176 LY_CHECK_RET(parse_yangversion(ctx, in, &mod->version, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004177 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004178 case LY_STMT_NAMESPACE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004179 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->mod->ns, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004180 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004181 case LY_STMT_PREFIX:
Michal Vasko63f3d842020-07-08 10:10:14 +02004182 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PREFIX, 0, &mod->mod->prefix, Y_IDENTIF_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004183 break;
4184
4185 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004186 case LY_STMT_INCLUDE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004187 LY_CHECK_RET(parse_include(ctx, mod->mod->name, in, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004188 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004189 case LY_STMT_IMPORT:
Michal Vasko63f3d842020-07-08 10:10:14 +02004190 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, in, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004191 break;
4192
4193 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004194 case LY_STMT_ORGANIZATION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004195 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->mod->org, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004196 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004197 case LY_STMT_CONTACT:
Michal Vasko63f3d842020-07-08 10:10:14 +02004198 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_CONTACT, 0, &mod->mod->contact, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004199 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004200 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004201 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->mod->dsc, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004202 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004203 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004204 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &mod->mod->ref, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004205 break;
4206
4207 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004208 case LY_STMT_REVISION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004209 LY_CHECK_RET(parse_revision(ctx, in, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004210 break;
4211
4212 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004213 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02004214 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci0f969882020-08-21 16:56:47 +02004215 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02004216 case LY_STMT_ANYXML:
Michal Vasko63f3d842020-07-08 10:10:14 +02004217 LY_CHECK_RET(parse_any(ctx, in, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004218 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004219 case LY_STMT_CHOICE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004220 LY_CHECK_RET(parse_choice(ctx, in, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004221 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004222 case LY_STMT_CONTAINER:
Michal Vasko63f3d842020-07-08 10:10:14 +02004223 LY_CHECK_RET(parse_container(ctx, in, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004224 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004225 case LY_STMT_LEAF:
Michal Vasko63f3d842020-07-08 10:10:14 +02004226 LY_CHECK_RET(parse_leaf(ctx, in, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004227 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004228 case LY_STMT_LEAF_LIST:
Michal Vasko63f3d842020-07-08 10:10:14 +02004229 LY_CHECK_RET(parse_leaflist(ctx, in, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004230 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004231 case LY_STMT_LIST:
Michal Vasko63f3d842020-07-08 10:10:14 +02004232 LY_CHECK_RET(parse_list(ctx, in, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004233 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004234 case LY_STMT_USES:
Michal Vasko63f3d842020-07-08 10:10:14 +02004235 LY_CHECK_RET(parse_uses(ctx, in, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004236 break;
4237
Radek Krejcid6b76452019-09-03 17:03:03 +02004238 case LY_STMT_AUGMENT:
Michal Vasko63f3d842020-07-08 10:10:14 +02004239 LY_CHECK_RET(parse_augment(ctx, in, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004240 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004241 case LY_STMT_DEVIATION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004242 LY_CHECK_RET(parse_deviation(ctx, in, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004243 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004244 case LY_STMT_EXTENSION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004245 LY_CHECK_RET(parse_extension(ctx, in, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004246 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004247 case LY_STMT_FEATURE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004248 LY_CHECK_RET(parse_feature(ctx, in, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004249 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004250 case LY_STMT_GROUPING:
Michal Vasko63f3d842020-07-08 10:10:14 +02004251 LY_CHECK_RET(parse_grouping(ctx, in, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004252 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004253 case LY_STMT_IDENTITY:
Michal Vasko63f3d842020-07-08 10:10:14 +02004254 LY_CHECK_RET(parse_identity(ctx, in, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004255 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004256 case LY_STMT_NOTIFICATION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004257 LY_CHECK_RET(parse_notif(ctx, in, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004258 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004259 case LY_STMT_RPC:
Michal Vasko63f3d842020-07-08 10:10:14 +02004260 LY_CHECK_RET(parse_action(ctx, in, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004261 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004262 case LY_STMT_TYPEDEF:
Michal Vasko63f3d842020-07-08 10:10:14 +02004263 LY_CHECK_RET(parse_typedef(ctx, NULL, in, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004264 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004265 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004266 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004267 break;
4268
4269 default:
David Sedlákb3077192019-06-19 10:55:37 +02004270 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004271 return LY_EVALID;
4272 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004273 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004274 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004275
Radek Krejci6d6556c2018-11-08 09:37:45 +01004276checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004277 /* finalize parent pointers to the reallocated items */
Michal Vaskob36053d2020-03-26 15:49:30 +01004278 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004279
Michal Vasko7fbc8162018-09-17 10:35:16 +02004280 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004281 if (!mod->mod->ns) {
David Sedlákb3077192019-06-19 10:55:37 +02004282 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004283 return LY_EVALID;
4284 } else if (!mod->mod->prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02004285 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004286 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004287 }
4288
Radek Krejcie9e987e2018-10-31 12:50:27 +01004289 /* submodules share the namespace with the module names, so there must not be
4290 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004291 dup = ly_ctx_get_submodule(PARSER_CTX(ctx), NULL, mod->mod->name, NULL);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004292 if (dup) {
David Sedlákb3077192019-06-19 10:55:37 +02004293 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004294 return LY_EVALID;
4295 }
4296
4297 return ret;
4298}
4299
4300/**
4301 * @brief Parse submodule substatements.
4302 *
4303 * @param[in] ctx yang parser context for logging.
Michal Vasko63f3d842020-07-08 10:10:14 +02004304 * @param[in,out] in Input structure.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004305 * @param[out] submod Parsed submodule structure.
4306 *
4307 * @return LY_ERR values.
4308 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004309LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02004310parse_submodule(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_submodule *submod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004311{
4312 LY_ERR ret = 0;
4313 char *buf, *word;
4314 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004315 enum ly_stmt kw, prev_kw = 0;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004316 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4317 struct lysp_submodule *dup;
4318
Michal Vaskoc3781c32020-10-06 14:04:08 +02004319 submod->is_submod = 1;
4320
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004321 /* submodule name */
Michal Vasko63f3d842020-07-08 10:10:14 +02004322 LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci011e4aa2020-09-04 15:22:31 +02004323 INSERT_WORD_RET(ctx, buf, submod->name, word, word_len);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004324
Michal Vasko63f3d842020-07-08 10:10:14 +02004325 YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004326
4327#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004328 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 +01004329
4330 switch (kw) {
4331 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004332 case LY_STMT_BELONGS_TO:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004333 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4334 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004335 case LY_STMT_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004336 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4337 break;
4338 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004339 case LY_STMT_INCLUDE:
4340 case LY_STMT_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004341 CHECK_ORDER(Y_MOD_LINKAGE);
4342 break;
4343 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004344 case LY_STMT_ORGANIZATION:
4345 case LY_STMT_CONTACT:
4346 case LY_STMT_DESCRIPTION:
4347 case LY_STMT_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004348 CHECK_ORDER(Y_MOD_META);
4349 break;
4350
4351 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004352 case LY_STMT_REVISION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004353 CHECK_ORDER(Y_MOD_REVISION);
4354 break;
4355 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004356 case LY_STMT_ANYDATA:
4357 case LY_STMT_ANYXML:
4358 case LY_STMT_AUGMENT:
4359 case LY_STMT_CHOICE:
4360 case LY_STMT_CONTAINER:
4361 case LY_STMT_DEVIATION:
4362 case LY_STMT_EXTENSION:
4363 case LY_STMT_FEATURE:
4364 case LY_STMT_GROUPING:
4365 case LY_STMT_IDENTITY:
4366 case LY_STMT_LEAF:
4367 case LY_STMT_LEAF_LIST:
4368 case LY_STMT_LIST:
4369 case LY_STMT_NOTIFICATION:
4370 case LY_STMT_RPC:
4371 case LY_STMT_TYPEDEF:
4372 case LY_STMT_USES:
4373 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004374 mod_stmt = Y_MOD_BODY;
4375 break;
4376 default:
4377 /* error handled in the next switch */
4378 break;
4379 }
4380#undef CHECK_ORDER
4381
4382 prev_kw = kw;
4383 switch (kw) {
4384 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004385 case LY_STMT_YANG_VERSION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004386 LY_CHECK_RET(parse_yangversion(ctx, in, &submod->version, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004387 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004388 case LY_STMT_BELONGS_TO:
Michal Vaskoc3781c32020-10-06 14:04:08 +02004389 LY_CHECK_RET(parse_belongsto(ctx, in, &submod->prefix, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004390 break;
4391
4392 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004393 case LY_STMT_INCLUDE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004394 LY_CHECK_RET(parse_include(ctx, submod->name, in, &submod->includes));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004395 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004396 case LY_STMT_IMPORT:
Michal Vasko63f3d842020-07-08 10:10:14 +02004397 LY_CHECK_RET(parse_import(ctx, submod->prefix, in, &submod->imports));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004398 break;
4399
4400 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004401 case LY_STMT_ORGANIZATION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004402 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004403 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004404 case LY_STMT_CONTACT:
Michal Vasko63f3d842020-07-08 10:10:14 +02004405 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004406 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004407 case LY_STMT_DESCRIPTION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004408 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004409 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004410 case LY_STMT_REFERENCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004411 LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004412 break;
4413
4414 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004415 case LY_STMT_REVISION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004416 LY_CHECK_RET(parse_revision(ctx, in, &submod->revs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004417 break;
4418
4419 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004420 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02004421 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
Radek Krejci0f969882020-08-21 16:56:47 +02004422 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02004423 case LY_STMT_ANYXML:
Michal Vasko63f3d842020-07-08 10:10:14 +02004424 LY_CHECK_RET(parse_any(ctx, in, kw, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004425 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004426 case LY_STMT_CHOICE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004427 LY_CHECK_RET(parse_choice(ctx, in, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004428 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004429 case LY_STMT_CONTAINER:
Michal Vasko63f3d842020-07-08 10:10:14 +02004430 LY_CHECK_RET(parse_container(ctx, in, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004431 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004432 case LY_STMT_LEAF:
Michal Vasko63f3d842020-07-08 10:10:14 +02004433 LY_CHECK_RET(parse_leaf(ctx, in, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004434 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004435 case LY_STMT_LEAF_LIST:
Michal Vasko63f3d842020-07-08 10:10:14 +02004436 LY_CHECK_RET(parse_leaflist(ctx, in, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004437 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004438 case LY_STMT_LIST:
Michal Vasko63f3d842020-07-08 10:10:14 +02004439 LY_CHECK_RET(parse_list(ctx, in, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004440 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004441 case LY_STMT_USES:
Michal Vasko63f3d842020-07-08 10:10:14 +02004442 LY_CHECK_RET(parse_uses(ctx, in, NULL, &submod->data));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004443 break;
4444
Radek Krejcid6b76452019-09-03 17:03:03 +02004445 case LY_STMT_AUGMENT:
Michal Vasko63f3d842020-07-08 10:10:14 +02004446 LY_CHECK_RET(parse_augment(ctx, in, NULL, &submod->augments));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004447 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004448 case LY_STMT_DEVIATION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004449 LY_CHECK_RET(parse_deviation(ctx, in, &submod->deviations));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004450 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004451 case LY_STMT_EXTENSION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004452 LY_CHECK_RET(parse_extension(ctx, in, &submod->extensions));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004453 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004454 case LY_STMT_FEATURE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004455 LY_CHECK_RET(parse_feature(ctx, in, &submod->features));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004456 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004457 case LY_STMT_GROUPING:
Michal Vasko63f3d842020-07-08 10:10:14 +02004458 LY_CHECK_RET(parse_grouping(ctx, in, NULL, &submod->groupings));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004459 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004460 case LY_STMT_IDENTITY:
Michal Vasko63f3d842020-07-08 10:10:14 +02004461 LY_CHECK_RET(parse_identity(ctx, in, &submod->identities));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004462 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004463 case LY_STMT_NOTIFICATION:
Michal Vasko63f3d842020-07-08 10:10:14 +02004464 LY_CHECK_RET(parse_notif(ctx, in, NULL, &submod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004465 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004466 case LY_STMT_RPC:
Michal Vasko63f3d842020-07-08 10:10:14 +02004467 LY_CHECK_RET(parse_action(ctx, in, NULL, &submod->rpcs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004468 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004469 case LY_STMT_TYPEDEF:
Michal Vasko63f3d842020-07-08 10:10:14 +02004470 LY_CHECK_RET(parse_typedef(ctx, NULL, in, &submod->typedefs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004471 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004472 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko63f3d842020-07-08 10:10:14 +02004473 LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004474 break;
4475
4476 default:
David Sedlákb3077192019-06-19 10:55:37 +02004477 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004478 return LY_EVALID;
4479 }
4480 }
4481 LY_CHECK_RET(ret);
4482
4483checks:
4484 /* finalize parent pointers to the reallocated items */
Michal Vaskob36053d2020-03-26 15:49:30 +01004485 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments,
Michal Vasko69730152020-10-09 16:30:07 +02004486 submod->rpcs, submod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004487
4488 /* mandatory substatements */
Michal Vaskoc3781c32020-10-06 14:04:08 +02004489 if (!submod->prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02004490 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004491 return LY_EVALID;
4492 }
4493
4494 /* submodules share the namespace with the module names, so there must not be
4495 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004496 dup = ly_ctx_get_submodule(PARSER_CTX(ctx), NULL, submod->name, NULL);
Michal Vaskoc3781c32020-10-06 14:04:08 +02004497 /* main modules may have different revisions */
4498 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
David Sedlákb3077192019-06-19 10:55:37 +02004499 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004500 return LY_EVALID;
4501 }
4502
Michal Vasko7fbc8162018-09-17 10:35:16 +02004503 return ret;
4504}
4505
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004506/**
4507 * @brief Skip any redundant characters, namely whitespaces and comments.
4508 *
4509 * @param[in] ctx Yang parser context.
4510 * @param[in] in Input structure.
4511 * @return LY_SUCCESS on success.
4512 * @return LY_EVALID on invalid comment.
4513 */
4514static LY_ERR
4515skip_redundant_chars(struct lys_yang_parser_ctx *ctx, struct ly_in *in)
4516{
4517 /* read some trailing spaces, new lines, or comments */
4518 while (in->current[0]) {
4519 if (!strncmp(in->current, "//", 2)) {
4520 /* one-line comment */
4521 ly_in_skip(in, 2);
4522 LY_CHECK_RET(skip_comment(ctx, in, 1));
4523 } else if (!strncmp(in->current, "/*", 2)) {
4524 /* block comment */
4525 ly_in_skip(in, 2);
4526 LY_CHECK_RET(skip_comment(ctx, in, 2));
4527 } else if (isspace(in->current[0])) {
4528 /* whitespace */
4529 ly_in_skip(in, 1);
4530 } else {
4531 break;
4532 }
4533 }
4534
4535 return LY_SUCCESS;
4536}
4537
Radek Krejcid4557c62018-09-17 11:42:09 +02004538LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01004539yang_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 +02004540 struct ly_in *in, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004541{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004542 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004543 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004544 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004545 enum ly_stmt kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004546 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004547
David Sedlák1b623122019-08-05 15:27:49 +02004548 /* create context */
4549 *context = calloc(1, sizeof **context);
4550 LY_CHECK_ERR_RET(!(*context), LOGMEM(ly_ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01004551 (*context)->format = LYS_IN_YANG;
Michal Vasko405cc9e2020-12-01 12:01:27 +01004552 (*context)->unres = main_ctx->unres;
Radek Krejci99435242019-09-05 16:19:15 +02004553 (*context)->pos_type = LY_VLOG_LINE;
David Sedlák1b623122019-08-05 15:27:49 +02004554 (*context)->line = 1;
4555
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004556 mod_p = calloc(1, sizeof *mod_p);
4557 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ly_ctx); ret = LY_EMEM, cleanup);
4558 mod_p->mod = main_ctx->parsed_mod->mod;
4559 mod_p->parsing = 1;
4560 (*context)->parsed_mod = (struct lysp_module *)mod_p;
4561
David Sedlák1b623122019-08-05 15:27:49 +02004562 /* map the typedefs and groupings list from main context to the submodule's context */
4563 memcpy(&(*context)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
4564 memcpy(&(*context)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
4565
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004566 /* skip redundant but valid characters at the beginning */
4567 ret = skip_redundant_chars(*context, in);
4568 LY_CHECK_GOTO(ret, cleanup);
4569
Michal Vasko7fbc8162018-09-17 10:35:16 +02004570 /* "module"/"submodule" */
Michal Vasko63f3d842020-07-08 10:10:14 +02004571 ret = get_keyword(*context, in, &kw, &word, &word_len);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004572 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004573
Radek Krejcid6b76452019-09-03 17:03:03 +02004574 if (kw == LY_STMT_MODULE) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004575 LOGERR(ly_ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004576 ret = LY_EINVAL;
4577 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02004578 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02004579 LOGVAL_PARSER(*context, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004580 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004581 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004582 }
4583
Michal Vasko7fbc8162018-09-17 10:35:16 +02004584 /* substatements */
Michal Vasko63f3d842020-07-08 10:10:14 +02004585 ret = parse_submodule(*context, in, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004586 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004587
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004588 /* skip redundant but valid characters at the end */
4589 ret = skip_redundant_chars(*context, in);
4590 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko63f3d842020-07-08 10:10:14 +02004591 if (in->current[0]) {
4592 LOGVAL_PARSER(*context, LY_VCODE_TRAILING_SUBMOD, 15, in->current, strlen(in->current) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004593 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004594 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004595 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004596
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004597 mod_p->parsing = 0;
4598 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004599
Radek Krejcibbe09a92018-11-08 09:36:54 +01004600cleanup:
4601 if (ret) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004602 lysp_module_free((struct lysp_module *)mod_p);
Michal Vaskob36053d2020-03-26 15:49:30 +01004603 yang_parser_ctx_free(*context);
David Sedlák1b623122019-08-05 15:27:49 +02004604 *context = NULL;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004605 }
4606
4607 return ret;
4608}
4609
4610LY_ERR
Michal Vasko405cc9e2020-12-01 12:01:27 +01004611yang_parse_module(struct lys_yang_parser_ctx **context, struct ly_in *in, struct lys_module *mod, struct lys_glob_unres *unres)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004612{
4613 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004614 char *word;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004615 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004616 enum ly_stmt kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004617 struct lysp_module *mod_p = NULL;
4618
David Sedlák1b623122019-08-05 15:27:49 +02004619 /* create context */
4620 *context = calloc(1, sizeof **context);
4621 LY_CHECK_ERR_RET(!(*context), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01004622 (*context)->format = LYS_IN_YANG;
Michal Vasko405cc9e2020-12-01 12:01:27 +01004623 (*context)->unres = unres;
Radek Krejci335332a2019-09-05 13:03:35 +02004624 (*context)->pos_type = LY_VLOG_LINE;
David Sedlák1b623122019-08-05 15:27:49 +02004625 (*context)->line = 1;
4626
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004627 mod_p = calloc(1, sizeof *mod_p);
4628 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
4629 mod_p->mod = mod;
4630 mod_p->parsing = 1;
4631 (*context)->parsed_mod = mod_p;
4632
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004633 /* skip redundant but valid characters at the beginning */
4634 ret = skip_redundant_chars(*context, in);
4635 LY_CHECK_GOTO(ret, cleanup);
4636
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004637 /* "module"/"submodule" */
Michal Vasko63f3d842020-07-08 10:10:14 +02004638 ret = get_keyword(*context, in, &kw, &word, &word_len);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004639 LY_CHECK_GOTO(ret, cleanup);
4640
Radek Krejcid6b76452019-09-03 17:03:03 +02004641 if (kw == LY_STMT_SUBMODULE) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02004642 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 +01004643 ret = LY_EINVAL;
4644 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02004645 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02004646 LOGVAL_PARSER((*context), LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004647 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004648 goto cleanup;
4649 }
4650
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004651 /* substatements */
Michal Vasko63f3d842020-07-08 10:10:14 +02004652 ret = parse_module(*context, in, mod_p);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004653 LY_CHECK_GOTO(ret, cleanup);
4654
Michal Vasko69e6bbb2020-11-04 17:11:46 +01004655 /* skip redundant but valid characters at the end */
4656 ret = skip_redundant_chars(*context, in);
4657 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko63f3d842020-07-08 10:10:14 +02004658 if (in->current[0]) {
4659 LOGVAL_PARSER(*context, LY_VCODE_TRAILING_MOD, 15, in->current, strlen(in->current) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004660 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004661 goto cleanup;
4662 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004663
4664 mod_p->parsing = 0;
4665 mod->parsed = mod_p;
4666
4667cleanup:
4668 if (ret) {
4669 lysp_module_free(mod_p);
Michal Vaskob36053d2020-03-26 15:49:30 +01004670 yang_parser_ctx_free(*context);
David Sedlák1b623122019-08-05 15:27:49 +02004671 *context = NULL;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004672 }
4673
Michal Vasko7fbc8162018-09-17 10:35:16 +02004674 return ret;
4675}