blob: f4c1b5554ca7640776fbd51951cb7807033da00f [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 Vasko7fbc8162018-09-17 10:35:16 +020014
15#include "common.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020016
17#include <assert.h>
18#include <ctype.h>
19#include <errno.h>
20#include <stdint.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
Michal Vasko7fbc8162018-09-17 10:35:16 +020025#include "context.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020026#include "dict.h"
27#include "extensions.h"
28#include "log.h"
29#include "set.h"
30#include "tree.h"
31#include "tree_schema.h"
Radek Krejci70853c52018-10-15 14:46:16 +020032#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020033
Radek Krejciceaf2122019-01-02 15:03:26 +010034/**
35 * @brief Try to find object with MEMBER string matching the IDENT in the given ARRAY.
36 * Macro logs an error message and returns LY_EVALID in case of existence of a matching object.
37 *
38 * @param[in] CTX yang parser context for logging.
39 * @param[in] ARRAY [sized array](@ref sizedarrays) of a generic objects with member named MEMBER to search.
40 * @param[in] MEMBER Name of the member of the objects in the ARRAY to compare.
41 * @param[in] STMT Name of the compared YANG statements for logging.
42 * @param[in] IDENT String trying to find in the ARRAY's objects inside the MEMBER member.
43 */
Radek Krejcifaa1eac2018-10-30 14:34:55 +010044#define CHECK_UNIQUENESS(CTX, ARRAY, MEMBER, STMT, IDENT) \
45 if (ARRAY) { \
46 for (unsigned int u = 0; u < LY_ARRAY_SIZE(ARRAY) - 1; ++u) { \
47 if (!strcmp((ARRAY)[u].MEMBER, IDENT)) { \
David Sedlákb3077192019-06-19 10:55:37 +020048 LOGVAL_PARSER(CTX, LY_VCODE_DUPIDENT, IDENT, STMT); \
Radek Krejcifaa1eac2018-10-30 14:34:55 +010049 return LY_EVALID; \
50 } \
51 } \
52 }
53
Radek Krejciceaf2122019-01-02 15:03:26 +010054/**
55 * @brief Insert WORD into the libyang context's dictionary and store as TARGET.
56 * @param[in] CTX yang parser context to access libyang context.
57 * @param[in] BUF buffer in case the word is not a constant and can be inserted directly (zero-copy)
58 * @param[out] TARGET variable where to store the pointer to the inserted value.
59 * @param[in] WORD string to store.
60 * @param[in] LEN length of the string in WORD to store.
61 */
Radek Krejci9fcacc12018-10-11 15:59:11 +020062#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
63 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
Radek Krejcif09e4e82019-06-14 15:08:11 +020064 else {(TARGET) = lydict_insert((CTX)->ctx, LEN ? WORD : "", LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020065
Radek Krejciceaf2122019-01-02 15:03:26 +010066/**
67 * @brief Move the DATA pointer by COUNT items. Also updates the indent value in yang parser context
68 * @param[in] CTX yang parser context to update its indent value.
69 * @param[in,out] DATA pointer to move
70 * @param[in] COUNT number of items for which the DATA pointer is supposed to move on.
71 */
Radek Krejci2b610482019-01-02 13:36:09 +010072#define MOVE_INPUT(CTX, DATA, COUNT) (*(DATA))+=COUNT;(CTX)->indent+=COUNT
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020073
Michal Vaskoea5abea2018-09-18 13:10:54 +020074/**
75 * @brief Loop through all substatements providing, return if there are none.
76 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020077 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020078 * @param[in] DATA Raw data to read from.
79 * @param[out] KW YANG keyword read.
80 * @param[out] WORD Pointer to the keyword itself.
81 * @param[out] WORD_LEN Length of the keyword.
82 * @param[out] ERR Variable for error storing.
83 *
84 * @return In case there are no substatements or a fatal error encountered.
85 */
Radek Krejci6d6556c2018-11-08 09:37:45 +010086#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010087 LY_CHECK_RET(get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020088 if (KW == YANG_SEMICOLON) { \
Radek Krejci6d6556c2018-11-08 09:37:45 +010089 CHECKGOTO; \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010090 return LY_SUCCESS; \
Michal Vasko7fbc8162018-09-17 10:35:16 +020091 } \
92 if (KW != YANG_LEFT_BRACE) { \
David Sedlákb3077192019-06-19 10:55:37 +020093 LOGVAL_PARSER(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020094 return LY_EVALID; \
95 } \
96 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
97 !ERR && (KW != YANG_RIGHT_BRACE); \
98 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
99
Radek Krejciceaf2122019-01-02 15:03:26 +0100100/**
101 * @brief Check module version is at least 2 (YANG 1.1) because of the keyword presence.
102 * Logs error message and returns LY_EVALID in case of module in YANG version 1.0.
103 * @param[in] CTX yang parser context to get current module and for logging.
104 * @param[in] KW keyword allowed only in YANG version 1.1 (or later) - for logging.
105 * @param[in] PARENT parent statement where the KW is present - for logging.
106 */
107#define YANG_CHECK_STMTVER2_RET(CTX, KW, PARENT) \
David Sedlákb3077192019-06-19 10:55:37 +0200108 if ((CTX)->mod_version < 2) {LOGVAL_PARSER((CTX), LY_VCODE_INCHILDSTMT2, KW, PARENT); return LY_EVALID;}
Radek Krejci10113652018-11-14 16:56:50 +0100109
Radek Krejcif09e4e82019-06-14 15:08:11 +0200110#define YANG_CHECK_NONEMPTY(CTX, OBJECT, VALUE_LEN, STMT) \
111 if (!VALUE_LEN) { \
112 LOGWRN((CTX)->ctx, "Empty argument of %s statement does not make sense.", STMT); \
113 }
114
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200115LY_ERR parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
116LY_ERR parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
117LY_ERR parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
118LY_ERR parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
119LY_ERR parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
120LY_ERR parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200121
Radek Krejci7fc68292019-06-12 13:51:09 +0200122static LY_ERR parse_finalize_reallocated(struct lys_parser_ctx *ctx, struct lysp_grp *groupings, struct lysp_augment *augments,
123 struct lysp_action *actions, struct lysp_notif *notifs);
124
Michal Vaskoea5abea2018-09-18 13:10:54 +0200125/**
126 * @brief Add another character to dynamic buffer, a low-level function.
127 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200128 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200129 *
Radek Krejci404251e2018-10-09 12:06:44 +0200130 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200131 * @param[in, out] input Input string to process.
132 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200133 * @param[in,out] buf Buffer to use, can be moved by realloc().
134 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200135 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200136 *
137 * @return LY_ERR values.
138 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200139LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200140buf_add_char(struct ly_ctx *ctx, const char **input, size_t len, char **buf, size_t *buf_len, size_t *buf_used)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200141{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200142 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200143 *buf_len += 16;
144 *buf = ly_realloc(*buf, *buf_len);
145 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
146 }
Radek Krejcic0917392019-04-10 13:04:04 +0200147 if (*buf_used) {
148 memcpy(&(*buf)[*buf_used], *input, len);
149 } else {
150 memcpy(*buf, *input, len);
151 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200152
Radek Krejci44ceedc2018-10-02 15:54:31 +0200153 (*buf_used) += len;
154 (*input) += len;
155
Michal Vasko7fbc8162018-09-17 10:35:16 +0200156 return LY_SUCCESS;
157}
158
Michal Vaskoea5abea2018-09-18 13:10:54 +0200159/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200160 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
161 *
162 * @param[in] ctx yang parser context for logging.
163 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
164 * when function returns.
165 * @param[in] arg Type of the input string to select method of checking character validity.
166 * @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 +0200167 * 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 +0200168 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
169 * @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 +0200170 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200171 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
David Sedlák40bb13b2019-07-10 14:34:18 +0200172 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
173 * 0 - colon not yet found (no prefix)
174 * 1 - \p c is the colon character
175 * 2 - prefix already processed, now processing the identifier
Michal Vaskoea5abea2018-09-18 13:10:54 +0200176 *
177 * @return LY_ERR values.
178 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200179LY_ERR
David Sedlák40bb13b2019-07-10 14:34:18 +0200180buf_store_char(struct lys_parser_ctx *ctx, const char **input, enum yang_arg arg, char **word_p,
181 size_t *word_len, char **word_b, size_t *buf_len, int need_buf, int *prefix)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200182{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200183 unsigned int c;
184 size_t len;
185
Radek Krejcif29b7c32019-04-09 16:17:49 +0200186 /* check valid combination of input paremeters - if need_buf specified, word_b must be provided */
187 assert(!need_buf || (need_buf && word_b));
188
Radek Krejci44ceedc2018-10-02 15:54:31 +0200189 /* get UTF8 code point (and number of bytes coding the character) */
190 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
David Sedlákb3077192019-06-19 10:55:37 +0200191 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200192 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200193 if (c == '\n') {
194 ctx->indent = 0;
195 } else {
196 /* note - even the multibyte character is count as 1 */
197 ++ctx->indent;
198 }
199
Radek Krejci44ceedc2018-10-02 15:54:31 +0200200 /* check character validity */
201 switch (arg) {
202 case Y_IDENTIF_ARG:
David Sedlák4a650532019-07-10 11:55:18 +0200203 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, !(*word_len), NULL));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200204 break;
205 case Y_PREF_IDENTIF_ARG:
David Sedlák40bb13b2019-07-10 14:34:18 +0200206 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, !(*word_len), prefix));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200207 break;
208 case Y_STR_ARG:
209 case Y_MAYBE_STR_ARG:
David Sedlák4a650532019-07-10 11:55:18 +0200210 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200211 break;
212 }
213
Michal Vasko7fbc8162018-09-17 10:35:16 +0200214 if (word_b && *word_b) {
215 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200216 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200217 return LY_EMEM;
218 }
219
220 /* in case of realloc */
221 *word_p = *word_b;
Radek Krejcif29b7c32019-04-09 16:17:49 +0200222 } else if (word_b && need_buf) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200223 /* first time we need a buffer, copy everything read up to now */
224 if (*word_len) {
225 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200226 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200227 *buf_len = *word_len;
228 memcpy(*word_b, *word_p, *word_len);
229 }
230
231 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200232 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200233 return LY_EMEM;
234 }
235
236 /* in case of realloc */
237 *word_p = *word_b;
238 } else {
239 /* just remember the first character pointer */
240 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200241 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200242 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200243 /* ... and update the word's length */
244 (*word_len) += len;
245 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200246 }
247
248 return LY_SUCCESS;
249}
250
Michal Vaskoea5abea2018-09-18 13:10:54 +0200251/**
252 * @brief Skip YANG comment in data.
253 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200254 * @param[in] ctx yang parser context for logging.
255 * @param[in,out] data Data to read from, automatically moved after the comment.
256 * @param[in] comment Type of the comment to process:
257 * 1 for a one-line comment,
258 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200259 *
260 * @return LY_ERR values.
261 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200262LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200263skip_comment(struct lys_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200264{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200265 /* internal statuses: 0 - comment ended,
266 * 1 - in line comment,
267 * 2 - in block comment,
268 * 3 - in block comment with last read character '*'
269 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200270 while (**data && comment) {
271 switch (comment) {
272 case 1:
273 if (**data == '\n') {
274 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200275 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200276 }
277 break;
278 case 2:
279 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200280 comment = 3;
281 } else if (**data == '\n') {
282 ++ctx->line;
283 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200284 break;
285 case 3:
286 if (**data == '/') {
287 comment = 0;
Radek Krejci5b930492019-06-11 14:54:08 +0200288 } else if (**data != '*') {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200289 if (**data == '\n') {
290 ++ctx->line;
291 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200292 comment = 2;
293 }
294 break;
295 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200296 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200297 }
298
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200299 if (**data == '\n') {
300 ctx->indent = 0;
301 } else {
302 ++ctx->indent;
303 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200304 ++(*data);
305 }
306
307 if (!**data && (comment > 1)) {
David Sedlákb3077192019-06-19 10:55:37 +0200308 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Unexpected end-of-input, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200309 return LY_EVALID;
310 }
311
312 return LY_SUCCESS;
313}
314
Michal Vaskoea5abea2018-09-18 13:10:54 +0200315/**
316 * @brief Read a quoted string from data.
317 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200318 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200319 * @param[in,out] data Data to read from, always moved to currently handled character.
320 * @param[in] arg Type of YANG keyword argument expected.
321 * @param[out] word_p Pointer to the read quoted string.
322 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
323 * set to NULL. Otherwise equal to \p word_p.
324 * @param[out] word_len Length of the read quoted string.
325 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
326 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
327 * indenation in the final quoted string.
328 *
329 * @return LY_ERR values.
330 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200331static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200332read_qstring(struct lys_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len,
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200333 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200334{
335 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
336 * 4 - string finished, now skipping whitespaces looking for +,
337 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200338 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200339 const char *c;
David Sedlák40bb13b2019-07-10 14:34:18 +0200340 int prefix = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200341
342 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200343 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200344 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200345 } else {
346 assert(**data == '\'');
347 string = 1;
348 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200349 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200350
351 while (**data && string) {
352 switch (string) {
353 case 1:
354 switch (**data) {
355 case '\'':
356 /* string may be finished, but check for + */
357 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200358 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200359 break;
360 default:
361 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200362 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200363 break;
364 }
365 break;
366 case 2:
367 switch (**data) {
368 case '\"':
369 /* string may be finished, but check for + */
370 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200371 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200372 break;
373 case '\\':
374 /* special character following */
375 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200376 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200377 break;
378 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200379 if (current_indent < block_indent) {
380 ++current_indent;
381 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200382 } else {
383 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200384 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200385 }
386 break;
387 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200388 if (current_indent < block_indent) {
389 assert(need_buf);
390 current_indent += 8;
391 ctx->indent += 8;
392 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
393 /* store leftover spaces from the tab */
394 c = " ";
David Sedlák40bb13b2019-07-10 14:34:18 +0200395 LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200396 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200397 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200398 } else {
399 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200400 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200401 /* additional characters for indentation - only 1 was count in buf_store_char */
402 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200403 }
404 break;
405 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200406 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200407 /* we will be removing the indents so we need our own buffer */
408 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200409
410 /* remove trailing tabs and spaces */
411 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
412 --(*word_len);
413 }
414
415 /* start indentation */
416 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200417 }
418
419 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200420 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200421
422 /* maintain line number */
423 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200424
425 /* reset context indentation counter for possible string after this one */
426 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200427 break;
428 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200429 /* first non-whitespace character, stop eating indentation */
430 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200431
432 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200433 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200434 break;
435 }
436 break;
437 case 3:
438 /* string encoded characters */
439 switch (**data) {
440 case 'n':
441 c = "\n";
442 break;
443 case 't':
444 c = "\t";
445 break;
446 case '\"':
447 c = *data;
448 break;
449 case '\\':
450 c = *data;
451 break;
452 default:
David Sedlákb3077192019-06-19 10:55:37 +0200453 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200454 return LY_EVALID;
455 }
456
457 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200458 LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200459
460 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200461 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200462 break;
463 case 4:
464 switch (**data) {
465 case '+':
466 /* string continues */
467 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200468 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200469 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200470 case '\n':
471 ++ctx->line;
472 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200473 case ' ':
474 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200475 /* just skip */
476 break;
477 default:
478 /* string is finished */
479 goto string_end;
480 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200481 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200482 break;
483 case 5:
484 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200485 case '\n':
486 ++ctx->line;
487 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200488 case ' ':
489 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200490 /* skip */
491 break;
492 case '\'':
493 string = 1;
494 break;
495 case '\"':
496 string = 2;
497 break;
498 default:
499 /* it must be quoted again */
David Sedlákb3077192019-06-19 10:55:37 +0200500 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200501 return LY_EVALID;
502 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200503 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200504 break;
505 default:
506 return LY_EINT;
507 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200508 }
509
510string_end:
Radek Krejci4e199f52019-05-28 09:09:28 +0200511 if (arg <= Y_PREF_IDENTIF_ARG && !(*word_len)) {
512 /* empty identifier */
David Sedlákb3077192019-06-19 10:55:37 +0200513 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Statement argument is required.");
Radek Krejci4e199f52019-05-28 09:09:28 +0200514 return LY_EVALID;
515 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200516 return LY_SUCCESS;
517}
518
Michal Vaskoea5abea2018-09-18 13:10:54 +0200519/**
520 * @brief Get another YANG string from the raw data.
521 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200522 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200523 * @param[in,out] data Data to read from, always moved to currently handled character.
524 * @param[in] arg Type of YANG keyword argument expected.
Radek Krejcid3ca0632019-04-16 16:54:54 +0200525 * @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 +0200526 * @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 +0200527 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
528 * set to NULL. Otherwise equal to \p word_p.
529 * @param[out] word_len Length of the read string.
530 *
531 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200532 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200533LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200534get_argument(struct lys_parser_ctx *ctx, const char **data, enum yang_arg arg,
Radek Krejcid3ca0632019-04-16 16:54:54 +0200535 uint16_t *flags, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200536{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200537 size_t buf_len = 0;
David Sedlák40bb13b2019-07-10 14:34:18 +0200538 int prefix = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200539 /* word buffer - dynamically allocated */
540 *word_b = NULL;
541
542 /* word pointer - just a pointer to data */
543 *word_p = NULL;
544
545 *word_len = 0;
546 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200547 switch (**data) {
548 case '\'':
549 case '\"':
550 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200551 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
David Sedlákb3077192019-06-19 10:55:37 +0200552 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data,
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200553 "unquoted string character, optsep, semicolon or opening brace");
554 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200555 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200556 if (flags) {
557 (*flags) |= (**data) == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
558 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100559 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200560 goto str_end;
561 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200562 if ((*data)[1] == '/') {
563 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200564 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100565 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200566 } else if ((*data)[1] == '*') {
567 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200568 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100569 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200570 } else {
571 /* not a comment after all */
David Sedlák40bb13b2019-07-10 14:34:18 +0200572 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0, &prefix));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200573 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200574 break;
575 case ' ':
576 if (*word_len) {
577 /* word is finished */
578 goto str_end;
579 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200580 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200581 break;
582 case '\t':
583 if (*word_len) {
584 /* word is finished */
585 goto str_end;
586 }
587 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200588 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200589
590 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200591 break;
592 case '\n':
593 if (*word_len) {
594 /* word is finished */
595 goto str_end;
596 }
597 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200598 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200599
600 /* track line numbers */
601 ++ctx->line;
602
603 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200604 break;
605 case ';':
606 case '{':
607 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
608 /* word is finished */
609 goto str_end;
610 }
611
David Sedlákb3077192019-06-19 10:55:37 +0200612 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200613 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200614 case '}':
615 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
David Sedlákb3077192019-06-19 10:55:37 +0200616 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data,
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200617 "unquoted string character, optsep, semicolon or opening brace");
618 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200619 default:
David Sedlák40bb13b2019-07-10 14:34:18 +0200620 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200621 break;
622 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200623 }
624
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200625 /* unexpected end of loop */
David Sedlákb3077192019-06-19 10:55:37 +0200626 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200627 return LY_EVALID;
628
Michal Vasko7fbc8162018-09-17 10:35:16 +0200629str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200630 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200631 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200632 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
633 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
634 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200635 *word_p = *word_b;
636 }
637
638 return LY_SUCCESS;
639}
640
Michal Vaskoea5abea2018-09-18 13:10:54 +0200641/**
642 * @brief Get another YANG keyword from the raw data.
643 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200644 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200645 * @param[in,out] data Data to read from, always moved to currently handled character.
646 * @param[out] kw YANG keyword read.
647 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
648 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
649 *
650 * @return LY_ERR values.
651 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200652LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200653get_keyword(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword *kw, char **word_p, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200654{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200655 int prefix;
656 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200657 unsigned int c;
658 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200659
660 if (word_p) {
661 *word_p = NULL;
662 *word_len = 0;
663 }
664
665 /* first skip "optsep", comments */
666 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200667 switch (**data) {
668 case '/':
669 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200670 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200671 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100672 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200673 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200674 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200675 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100676 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200677 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200678 /* error - not a comment after all, keyword cannot start with slash */
David Sedlákb3077192019-06-19 10:55:37 +0200679 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
Radek Krejcidcc7b322018-10-11 14:24:02 +0200680 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200681 }
Radek Krejci13028282019-06-11 14:56:48 +0200682 continue;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200683 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200684 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200685 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200686 ctx->indent = 0;
687 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200688 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200689 /* skip whitespaces (optsep) */
690 ++ctx->indent;
691 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200692 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200693 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200694 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200695 break;
696 default:
697 /* either a keyword start or an invalid character */
698 goto keyword_start;
699 }
700
701 ++(*data);
702 }
703
704keyword_start:
705 word_start = *data;
David Sedlák5f8f0332019-06-18 16:34:30 +0200706 *kw = lysp_match_kw(ctx, data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200707
David Sedlák1bccdfa2019-06-17 15:55:27 +0200708 if (*kw == YANG_SEMICOLON || *kw == YANG_LEFT_BRACE || *kw == YANG_RIGHT_BRACE) {
Radek Krejci626df482018-10-11 15:06:31 +0200709 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200710 }
711
712 if (*kw != YANG_NONE) {
713 /* make sure we have the whole keyword */
714 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200715 case '\n':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200716 case '\t':
Radek Krejciabdd8062019-06-11 16:44:19 +0200717 case ' ':
718 /* mandatory "sep" is just checked, not eaten so nothing in the context is updated */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200719 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200720 case ':':
721 /* keyword is not actually a keyword, but prefix of an extension.
722 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
723 * and we will be checking the keyword (extension instance) itself */
724 prefix = 1;
725 MOVE_INPUT(ctx, data, 1);
726 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200727 case '{':
728 /* allowed only for input and output statements which can be without arguments */
729 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
730 break;
731 }
732 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200733 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200734 MOVE_INPUT(ctx, data, 1);
David Sedlákb3077192019-06-19 10:55:37 +0200735 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
Radek Krejci44ceedc2018-10-02 15:54:31 +0200736 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200737 return LY_EVALID;
738 }
739 } else {
740 /* still can be an extension */
741 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200742extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200743 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200744 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
David Sedlákb3077192019-06-19 10:55:37 +0200745 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200746 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200747 /* check character validity */
David Sedlák4a650532019-07-10 11:55:18 +0200748 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200749 }
750 if (!**data) {
David Sedlákb3077192019-06-19 10:55:37 +0200751 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200752 return LY_EVALID;
753 }
754
755 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200756 if (prefix != 2) {
David Sedlákb3077192019-06-19 10:55:37 +0200757 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200758 return LY_EVALID;
759 }
760
761 *kw = YANG_CUSTOM;
762 }
Radek Krejci626df482018-10-11 15:06:31 +0200763success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200764 if (word_p) {
765 *word_p = (char *)word_start;
766 *word_len = *data - word_start;
767 }
768
769 return LY_SUCCESS;
770}
771
Michal Vaskoea5abea2018-09-18 13:10:54 +0200772/**
773 * @brief Parse extension instance substatements.
774 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200775 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200776 * @param[in,out] data Data to read from, always moved to currently handled character.
777 * @param[in] word Extension instance substatement name (keyword).
778 * @param[in] word_len Extension instance substatement name length.
779 * @param[in,out] child Children of this extension instance to add to.
780 *
781 * @return LY_ERR values.
782 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200783static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200784parse_ext_substmt(struct lys_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200785 struct lysp_stmt **child)
786{
787 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100788 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200789 enum yang_keyword kw;
790 struct lysp_stmt *stmt, *par_child;
791
792 stmt = calloc(1, sizeof *stmt);
793 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
794
Radek Krejcibb9b1982019-04-08 14:24:59 +0200795 /* insert into parent statements */
796 if (!*child) {
797 *child = stmt;
798 } else {
799 for (par_child = *child; par_child->next; par_child = par_child->next);
800 par_child->next = stmt;
801 }
802
Radek Krejci44ceedc2018-10-02 15:54:31 +0200803 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200804
805 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200806 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200807
Radek Krejci0ae092d2018-09-20 16:43:19 +0200808 if (word) {
809 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200810 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200811 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200812 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200813 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200814 }
815
Radek Krejci6d6556c2018-11-08 09:37:45 +0100816 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100817 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200818 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200819 return ret;
820}
821
Michal Vaskoea5abea2018-09-18 13:10:54 +0200822/**
823 * @brief Parse extension instance.
824 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200825 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200826 * @param[in,out] data Data to read from, always moved to currently handled character.
827 * @param[in] ext_name Extension instance substatement name (keyword).
828 * @param[in] ext_name_len Extension instance substatement name length.
829 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
830 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
831 * @param[in,out] exts Extension instances to add to.
832 *
833 * @return LY_ERR values.
834 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200835static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200836parse_ext(struct lys_parser_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200837 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
838{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100839 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200840 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200841 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200842 struct lysp_ext_instance *e;
843 enum yang_keyword kw;
844
Radek Krejci2c4e7172018-10-19 15:56:26 +0200845 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200846
847 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200848 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200849 e->insubstmt = insubstmt;
850 e->insubstmt_index = insubstmt_index;
851
852 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200853 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200854
Radek Krejci0ae092d2018-09-20 16:43:19 +0200855 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200856 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200857 }
858
Radek Krejci6d6556c2018-11-08 09:37:45 +0100859 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100860 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200861 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200862 return ret;
863}
864
Michal Vaskoea5abea2018-09-18 13:10:54 +0200865/**
866 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
867 * description, etc...
868 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200869 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200870 * @param[in,out] data Data to read from, always moved to currently handled character.
871 * @param[in] substmt Type of this substatement.
872 * @param[in] substmt_index Index of this substatement.
873 * @param[in,out] value Place to store the parsed value.
874 * @param[in] arg Type of the YANG keyword argument (of the value).
875 * @param[in,out] exts Extension instances to add to.
876 *
877 * @return LY_ERR values.
878 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200879static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200880parse_text_field(struct lys_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200881 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
882{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100883 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200884 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200885 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200886 enum yang_keyword kw;
887
888 if (*value) {
David Sedlákb3077192019-06-19 10:55:37 +0200889 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200890 return LY_EVALID;
891 }
892
893 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200894 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200895
896 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200897 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200898
Radek Krejci6d6556c2018-11-08 09:37:45 +0100899 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200900 switch (kw) {
901 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100902 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200903 break;
904 default:
David Sedlákb3077192019-06-19 10:55:37 +0200905 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200906 return LY_EVALID;
907 }
908 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200909 return ret;
910}
911
Michal Vaskoea5abea2018-09-18 13:10:54 +0200912/**
913 * @brief Parse the yang-version statement.
914 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200915 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200916 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100917 * @param[out] version Storage for the parsed information.
918 * @param[in, out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200919 *
920 * @return LY_ERR values.
921 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200922static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200923parse_yangversion(struct lys_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200924{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100925 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200926 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200927 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200928 enum yang_keyword kw;
929
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100930 if (*version) {
David Sedlákb3077192019-06-19 10:55:37 +0200931 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200932 return LY_EVALID;
933 }
934
935 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200936 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200937
938 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100939 *version = LYS_VERSION_1_0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200940 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100941 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200942 } else {
David Sedlákb3077192019-06-19 10:55:37 +0200943 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200944 free(buf);
945 return LY_EVALID;
946 }
947 free(buf);
948
Radek Krejci6d6556c2018-11-08 09:37:45 +0100949 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200950 switch (kw) {
951 case YANG_CUSTOM:
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100952 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200953 break;
954 default:
David Sedlákb3077192019-06-19 10:55:37 +0200955 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200956 return LY_EVALID;
957 }
958 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200959 return ret;
960}
961
Michal Vaskoea5abea2018-09-18 13:10:54 +0200962/**
963 * @brief Parse the belongs-to statement.
964 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200965 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200966 * @param[in,out] data Data to read from, always moved to currently handled character.
967 * @param[in,out] belongsto Place to store the parsed value.
968 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
969 * @param[in,out] exts Extension instances to add to.
970 *
971 * @return LY_ERR values.
972 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200973static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200974parse_belongsto(struct lys_parser_ctx *ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200975{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100976 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200977 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200978 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200979 enum yang_keyword kw;
980
981 if (*belongsto) {
David Sedlákb3077192019-06-19 10:55:37 +0200982 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200983 return LY_EVALID;
984 }
985
986 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200987 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200988
Radek Krejci44ceedc2018-10-02 15:54:31 +0200989 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejcif09e4e82019-06-14 15:08:11 +0200990
Radek Krejci6d6556c2018-11-08 09:37:45 +0100991 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200992 switch (kw) {
993 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100994 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200995 break;
996 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100997 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200998 break;
999 default:
David Sedlákb3077192019-06-19 10:55:37 +02001000 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001001 return LY_EVALID;
1002 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001003 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001004 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001005checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001006 /* mandatory substatements */
1007 if (!*prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02001008 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001009 return LY_EVALID;
1010 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001011 return ret;
1012}
1013
Michal Vaskoea5abea2018-09-18 13:10:54 +02001014/**
1015 * @brief Parse the revision-date statement.
1016 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001017 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001018 * @param[in,out] data Data to read from, always moved to currently handled character.
1019 * @param[in,out] rev Array to store the parsed value in.
1020 * @param[in,out] exts Extension instances to add to.
1021 *
1022 * @return LY_ERR values.
1023 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001024static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001025parse_revisiondate(struct lys_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001026{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001027 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001028 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001029 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001030 enum yang_keyword kw;
1031
1032 if (rev[0]) {
David Sedlákb3077192019-06-19 10:55:37 +02001033 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001034 return LY_EVALID;
1035 }
1036
1037 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001038 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001039
1040 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001041 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001042 free(buf);
1043 return LY_EVALID;
1044 }
1045
1046 /* store value and spend buf if allocated */
1047 strncpy(rev, word, word_len);
1048 free(buf);
1049
Radek Krejci6d6556c2018-11-08 09:37:45 +01001050 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001051 switch (kw) {
1052 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001053 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001054 break;
1055 default:
David Sedlákb3077192019-06-19 10:55:37 +02001056 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001057 return LY_EVALID;
1058 }
1059 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001060 return ret;
1061}
1062
Michal Vaskoea5abea2018-09-18 13:10:54 +02001063/**
1064 * @brief Parse the include statement.
1065 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001066 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001067 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001068 * @param[in,out] data Data to read from, always moved to currently handled character.
1069 * @param[in,out] includes Parsed includes to add to.
1070 *
1071 * @return LY_ERR values.
1072 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001073static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001074parse_include(struct lys_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001075{
Radek Krejcid33273d2018-10-25 14:55:52 +02001076 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001077 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001078 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001079 enum yang_keyword kw;
1080 struct lysp_include *inc;
1081
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001082 LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001083
1084 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001085 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001086
Radek Krejci086c7132018-10-26 15:29:04 +02001087 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1088
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001089 /* submodules share the namespace with the module names, so there must not be
1090 * a module of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001091 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
David Sedlákb3077192019-06-19 10:55:37 +02001092 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001093 return LY_EVALID;
1094 }
1095
Radek Krejci6d6556c2018-11-08 09:37:45 +01001096 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001097 switch (kw) {
1098 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001099 YANG_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001100 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001101 break;
1102 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001103 YANG_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001104 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001105 break;
1106 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001107 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001108 break;
1109 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001110 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001111 break;
1112 default:
David Sedlákb3077192019-06-19 10:55:37 +02001113 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001114 return LY_EVALID;
1115 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001116 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001117 return ret;
1118}
1119
Michal Vaskoea5abea2018-09-18 13:10:54 +02001120/**
1121 * @brief Parse the import statement.
1122 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001123 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001124 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001125 * @param[in,out] data Data to read from, always moved to currently handled character.
1126 * @param[in,out] imports Parsed imports to add to.
1127 *
1128 * @return LY_ERR values.
1129 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001130static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001131parse_import(struct lys_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001132{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001133 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001134 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001135 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001136 enum yang_keyword kw;
1137 struct lysp_import *imp;
1138
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001139 LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001140
1141 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001142 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001143 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001144
Radek Krejci6d6556c2018-11-08 09:37:45 +01001145 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001146 switch (kw) {
1147 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001148 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001149 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001150 break;
1151 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001152 YANG_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001153 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001154 break;
1155 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001156 YANG_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001157 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001158 break;
1159 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001160 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001161 break;
1162 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001163 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001164 break;
1165 default:
David Sedlákb3077192019-06-19 10:55:37 +02001166 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001167 return LY_EVALID;
1168 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001169 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001170 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001171checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001172 /* mandatory substatements */
David Sedlákb3077192019-06-19 10:55:37 +02001173 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001174
1175 return ret;
1176}
1177
Michal Vaskoea5abea2018-09-18 13:10:54 +02001178/**
1179 * @brief Parse the revision statement.
1180 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001181 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001182 * @param[in,out] data Data to read from, always moved to currently handled character.
1183 * @param[in,out] revs Parsed revisions to add to.
1184 *
1185 * @return LY_ERR values.
1186 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001187static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001188parse_revision(struct lys_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001190 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001191 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001192 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001193 enum yang_keyword kw;
1194 struct lysp_revision *rev;
1195
Radek Krejci2c4e7172018-10-19 15:56:26 +02001196 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001197
1198 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001199 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001200
1201 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001202 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001203 return LY_EVALID;
1204 }
1205
Radek Krejcib7db73a2018-10-24 14:18:40 +02001206 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001207 free(buf);
1208
Radek Krejci6d6556c2018-11-08 09:37:45 +01001209 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001210 switch (kw) {
1211 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001212 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001213 break;
1214 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001215 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001216 break;
1217 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001218 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001219 break;
1220 default:
David Sedlákb3077192019-06-19 10:55:37 +02001221 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001222 return LY_EVALID;
1223 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001224 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001225 return ret;
1226}
1227
Michal Vaskoea5abea2018-09-18 13:10:54 +02001228/**
1229 * @brief Parse a generic text field that can have more instances such as base.
1230 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001231 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001232 * @param[in,out] data Data to read from, always moved to currently handled character.
1233 * @param[in] substmt Type of this substatement.
1234 * @param[in,out] texts Parsed values to add to.
1235 * @param[in] arg Type of the expected argument.
1236 * @param[in,out] exts Extension instances to add to.
1237 *
1238 * @return LY_ERR values.
1239 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001240static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001241parse_text_fields(struct lys_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001242 struct lysp_ext_instance **exts)
1243{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001244 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001245 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001246 const char **item;
1247 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001248 enum yang_keyword kw;
1249
1250 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001251 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001252
1253 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001254 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001255
Radek Krejci151a5b72018-10-19 14:21:44 +02001256 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001257 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001258 switch (kw) {
1259 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001260 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001261 break;
1262 default:
David Sedlákb3077192019-06-19 10:55:37 +02001263 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001264 return LY_EVALID;
1265 }
1266 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001267 return ret;
1268}
1269
Michal Vaskoea5abea2018-09-18 13:10:54 +02001270/**
1271 * @brief Parse the config statement.
1272 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001273 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001274 * @param[in,out] data Data to read from, always moved to currently handled character.
1275 * @param[in,out] flags Flags to add to.
1276 * @param[in,out] exts Extension instances to add to.
1277 *
1278 * @return LY_ERR values.
1279 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001280static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001281parse_config(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001282{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001283 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001284 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001285 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001286 enum yang_keyword kw;
1287
1288 if (*flags & LYS_CONFIG_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001289 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001290 return LY_EVALID;
1291 }
1292
1293 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001294 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001295
1296 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1297 *flags |= LYS_CONFIG_W;
1298 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1299 *flags |= LYS_CONFIG_R;
1300 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001301 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001302 free(buf);
1303 return LY_EVALID;
1304 }
1305 free(buf);
1306
Radek Krejci6d6556c2018-11-08 09:37:45 +01001307 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001308 switch (kw) {
1309 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001310 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001311 break;
1312 default:
David Sedlákb3077192019-06-19 10:55:37 +02001313 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001314 return LY_EVALID;
1315 }
1316 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001317 return ret;
1318}
1319
Michal Vaskoea5abea2018-09-18 13:10:54 +02001320/**
1321 * @brief Parse the mandatory statement.
1322 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001323 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001324 * @param[in,out] data Data to read from, always moved to currently handled character.
1325 * @param[in,out] flags Flags to add to.
1326 * @param[in,out] exts Extension instances to add to.
1327 *
1328 * @return LY_ERR values.
1329 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001330static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001331parse_mandatory(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001332{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001333 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001334 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001335 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001336 enum yang_keyword kw;
1337
1338 if (*flags & LYS_MAND_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001339 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001340 return LY_EVALID;
1341 }
1342
1343 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001344 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001345
1346 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1347 *flags |= LYS_MAND_TRUE;
1348 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1349 *flags |= LYS_MAND_FALSE;
1350 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001351 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001352 free(buf);
1353 return LY_EVALID;
1354 }
1355 free(buf);
1356
Radek Krejci6d6556c2018-11-08 09:37:45 +01001357 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001358 switch (kw) {
1359 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001360 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001361 break;
1362 default:
David Sedlákb3077192019-06-19 10:55:37 +02001363 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001364 return LY_EVALID;
1365 }
1366 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001367 return ret;
1368}
1369
Michal Vaskoea5abea2018-09-18 13:10:54 +02001370/**
1371 * @brief Parse a restriction such as range or length.
1372 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001373 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001374 * @param[in,out] data Data to read from, always moved to currently handled character.
1375 * @param[in] restr_kw Type of this particular restriction.
1376 * @param[in,out] exts Extension instances to add to.
1377 *
1378 * @return LY_ERR values.
1379 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001380static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001381parse_restr(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr *restr)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001382{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001383 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001384 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001385 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001386 enum yang_keyword kw;
1387
1388 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001389 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001390
Radek Krejcif09e4e82019-06-14 15:08:11 +02001391 YANG_CHECK_NONEMPTY(ctx, NULL, word_len, ly_stmt2str(restr_kw));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001392 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001393 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001394 switch (kw) {
1395 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001396 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001397 break;
1398 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001399 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001400 break;
1401 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001402 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001403 break;
1404 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001405 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001406 break;
1407 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001408 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001409 break;
1410 default:
David Sedlákb3077192019-06-19 10:55:37 +02001411 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001412 return LY_EVALID;
1413 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001414 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001415 return ret;
1416}
1417
Michal Vaskoea5abea2018-09-18 13:10:54 +02001418/**
1419 * @brief Parse a restriction that can have more instances such as must.
1420 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001421 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001422 * @param[in,out] data Data to read from, always moved to currently handled character.
1423 * @param[in] restr_kw Type of this particular restriction.
1424 * @param[in,out] restrs Restrictions to add to.
1425 *
1426 * @return LY_ERR values.
1427 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001428static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001429parse_restrs(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr **restrs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001430{
1431 struct lysp_restr *restr;
1432
Radek Krejci2c4e7172018-10-19 15:56:26 +02001433 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001434 return parse_restr(ctx, data, restr_kw, restr);
1435}
1436
Michal Vaskoea5abea2018-09-18 13:10:54 +02001437/**
1438 * @brief Parse the status statement.
1439 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001440 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001441 * @param[in,out] data Data to read from, always moved to currently handled character.
1442 * @param[in,out] flags Flags to add to.
1443 * @param[in,out] exts Extension instances to add to.
1444 *
1445 * @return LY_ERR values.
1446 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001447static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001448parse_status(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001449{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001450 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001451 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001452 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001453 enum yang_keyword kw;
1454
1455 if (*flags & LYS_STATUS_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001456 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001457 return LY_EVALID;
1458 }
1459
1460 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001461 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001462
1463 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1464 *flags |= LYS_STATUS_CURR;
1465 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1466 *flags |= LYS_STATUS_DEPRC;
1467 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1468 *flags |= LYS_STATUS_OBSLT;
1469 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001470 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001471 free(buf);
1472 return LY_EVALID;
1473 }
1474 free(buf);
1475
Radek Krejci6d6556c2018-11-08 09:37:45 +01001476 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001477 switch (kw) {
1478 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001479 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001480 break;
1481 default:
David Sedlákb3077192019-06-19 10:55:37 +02001482 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001483 return LY_EVALID;
1484 }
1485 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001486 return ret;
1487}
1488
Michal Vaskoea5abea2018-09-18 13:10:54 +02001489/**
1490 * @brief Parse the when statement.
1491 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001492 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001493 * @param[in,out] data Data to read from, always moved to currently handled character.
1494 * @param[in,out] when_p When pointer to parse to.
1495 *
1496 * @return LY_ERR values.
1497 */
Radek Krejcif09e4e82019-06-14 15:08:11 +02001498LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001499parse_when(struct lys_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001500{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001501 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001502 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001503 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001504 enum yang_keyword kw;
1505 struct lysp_when *when;
1506
1507 if (*when_p) {
David Sedlákb3077192019-06-19 10:55:37 +02001508 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001509 return LY_EVALID;
1510 }
1511
1512 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001513 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001514
1515 /* get value */
Radek Krejci2f54df52019-06-21 10:59:19 +02001516 LY_CHECK_ERR_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len), free(when), LY_EMEM);
Radek Krejcif09e4e82019-06-14 15:08:11 +02001517 YANG_CHECK_NONEMPTY(ctx, when, word_len, "when");
Radek Krejci44ceedc2018-10-02 15:54:31 +02001518 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001519
Radek Krejcif09e4e82019-06-14 15:08:11 +02001520 *when_p = when;
1521
Radek Krejci6d6556c2018-11-08 09:37:45 +01001522 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001523 switch (kw) {
1524 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001525 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001526 break;
1527 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001528 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001529 break;
1530 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001531 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001532 break;
1533 default:
David Sedlákb3077192019-06-19 10:55:37 +02001534 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001535 return LY_EVALID;
1536 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001537 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001538 return ret;
1539}
1540
Michal Vaskoea5abea2018-09-18 13:10:54 +02001541/**
1542 * @brief Parse the anydata or anyxml statement.
1543 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001544 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001545 * @param[in,out] data Data to read from, always moved to currently handled character.
1546 * @param[in] kw Type of this particular keyword.
1547 * @param[in,out] siblings Siblings to add to.
1548 *
1549 * @return LY_ERR values.
1550 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02001551LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001552parse_any(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001553{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001554 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001555 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001556 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001557 struct lysp_node *iter;
1558 struct lysp_node_anydata *any;
1559
1560 /* create structure */
1561 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001562 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001563 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001564 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001565
1566 /* insert into siblings */
1567 if (!*siblings) {
1568 *siblings = (struct lysp_node *)any;
1569 } else {
1570 for (iter = *siblings; iter->next; iter = iter->next);
1571 iter->next = (struct lysp_node *)any;
1572 }
1573
1574 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001575 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001576 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001577
1578 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001579 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001580 switch (kw) {
1581 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001582 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001583 break;
1584 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001585 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001586 break;
1587 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001588 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001589 break;
1590 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001591 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001592 break;
1593 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001594 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001595 break;
1596 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001597 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001598 break;
1599 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001600 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001601 break;
1602 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001603 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001604 break;
1605 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001606 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001607 break;
1608 default:
David Sedlákb3077192019-06-19 10:55:37 +02001609 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001610 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001611 return LY_EVALID;
1612 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001613 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001614 return ret;
1615}
1616
Michal Vaskoea5abea2018-09-18 13:10:54 +02001617/**
1618 * @brief Parse the value or position statement. Substatement of type enum statement.
1619 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001620 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001621 * @param[in,out] data Data to read from, always moved to currently handled character.
1622 * @param[in] val_kw Type of this particular keyword.
1623 * @param[in,out] value Value to write to.
1624 * @param[in,out] flags Flags to write to.
1625 * @param[in,out] exts Extension instances to add to.
1626 *
1627 * @return LY_ERR values.
1628 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001629static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001630parse_type_enum_value_pos(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword val_kw, int64_t *value, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001631 struct lysp_ext_instance **exts)
1632{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001633 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001634 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001635 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001636 long int num;
1637 unsigned long int unum;
1638 enum yang_keyword kw;
1639
1640 if (*flags & LYS_SET_VALUE) {
David Sedlákb3077192019-06-19 10:55:37 +02001641 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001642 return LY_EVALID;
1643 }
1644 *flags |= LYS_SET_VALUE;
1645
1646 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001647 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001648
1649 if (!word_len || (word[0] == '+') || ((word[0] == '0') && (word_len > 1)) || ((val_kw == YANG_VALUE) && !strncmp(word, "-0", 2))) {
David Sedlákb3077192019-06-19 10:55:37 +02001650 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001651 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001652 }
1653
1654 errno = 0;
1655 if (val_kw == YANG_VALUE) {
1656 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001657 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlákb3077192019-06-19 10:55:37 +02001658 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001659 goto error;
1660 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001661 } else {
1662 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001663 if (unum > UINT64_C(4294967295)) {
David Sedlákb3077192019-06-19 10:55:37 +02001664 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001665 goto error;
1666 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001667 }
1668 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001669 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001670 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001671 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001672 }
1673 if (errno == ERANGE) {
David Sedlákb3077192019-06-19 10:55:37 +02001674 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001675 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001676 }
1677 if (val_kw == YANG_VALUE) {
1678 *value = num;
1679 } else {
1680 *value = unum;
1681 }
1682 free(buf);
1683
Radek Krejci6d6556c2018-11-08 09:37:45 +01001684 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001685 switch (kw) {
1686 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001687 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, val_kw == YANG_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001688 break;
1689 default:
David Sedlákb3077192019-06-19 10:55:37 +02001690 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001691 return LY_EVALID;
1692 }
1693 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001694 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001695
1696error:
1697 free(buf);
1698 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001699}
1700
Michal Vaskoea5abea2018-09-18 13:10:54 +02001701/**
1702 * @brief Parse the enum or bit statement. Substatement of type statement.
1703 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001704 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001705 * @param[in,out] data Data to read from, always moved to currently handled character.
1706 * @param[in] enum_kw Type of this particular keyword.
1707 * @param[in,out] enums Enums or bits to add to.
1708 *
1709 * @return LY_ERR values.
1710 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001711static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001712parse_type_enum(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword enum_kw, struct lysp_type_enum **enums)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001713{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001714 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001715 char *buf, *word;
Radek Krejci8b764662018-11-14 14:15:13 +01001716 size_t word_len, u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001717 enum yang_keyword kw;
1718 struct lysp_type_enum *enm;
1719
Radek Krejci2c4e7172018-10-19 15:56:26 +02001720 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001721
1722 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001723 LY_CHECK_RET(get_argument(ctx, data, enum_kw == YANG_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci8b764662018-11-14 14:15:13 +01001724 if (enum_kw == YANG_ENUM) {
1725 if (!word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001726 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Enum name must not be zero-length.");
Radek Krejci8b764662018-11-14 14:15:13 +01001727 free(buf);
1728 return LY_EVALID;
1729 } else if (isspace(word[0]) || isspace(word[word_len - 1])) {
David Sedlákb3077192019-06-19 10:55:37 +02001730 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Enum name must not have any leading or trailing whitespaces (\"%.*s\").",
Radek Krejci8b764662018-11-14 14:15:13 +01001731 word_len, word);
1732 free(buf);
1733 return LY_EVALID;
1734 } else {
1735 for (u = 0; u < word_len; ++u) {
1736 if (iscntrl(word[u])) {
1737 LOGWRN(ctx->ctx, "Control characters in enum name should be avoided (\"%.*s\", character number %d).",
1738 word_len, word, u + 1);
1739 break;
1740 }
1741 }
1742 }
1743 } else { /* YANG_BIT */
1744
1745 }
Radek Krejcif09e4e82019-06-14 15:08:11 +02001746 if (enum_kw == YANG_ENUM) {
1747 YANG_CHECK_NONEMPTY(ctx, NULL, word_len, "enum");
1748 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001749 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001750 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1751
Radek Krejci6d6556c2018-11-08 09:37:45 +01001752 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001753 switch (kw) {
1754 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001755 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001756 break;
1757 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001758 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001759 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001760 break;
1761 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001762 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001763 break;
1764 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001765 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001766 break;
1767 case YANG_VALUE:
1768 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001769 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001770 break;
1771 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001772 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001773 break;
1774 default:
David Sedlákb3077192019-06-19 10:55:37 +02001775 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001776 return LY_EVALID;
1777 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001778 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001779 return ret;
1780}
1781
Michal Vaskoea5abea2018-09-18 13:10:54 +02001782/**
1783 * @brief Parse the fraction-digits statement. Substatement of type statement.
1784 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001785 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001786 * @param[in,out] data Data to read from, always moved to currently handled character.
1787 * @param[in,out] fracdig Value to write to.
1788 * @param[in,out] exts Extension instances to add to.
1789 *
1790 * @return LY_ERR values.
1791 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001792static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001793parse_type_fracdigits(struct lys_parser_ctx *ctx, const char **data, uint8_t *fracdig, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001794{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001795 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001796 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001797 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001798 unsigned long int num;
1799 enum yang_keyword kw;
1800
1801 if (*fracdig) {
David Sedlákb3077192019-06-19 10:55:37 +02001802 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001803 return LY_EVALID;
1804 }
1805
1806 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001807 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001808
1809 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
David Sedlákb3077192019-06-19 10:55:37 +02001810 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001811 free(buf);
1812 return LY_EVALID;
1813 }
1814
1815 errno = 0;
1816 num = strtoul(word, &ptr, 10);
1817 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001818 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001819 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001820 free(buf);
1821 return LY_EVALID;
1822 }
1823 if ((errno == ERANGE) || (num > 18)) {
David Sedlákb3077192019-06-19 10:55:37 +02001824 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001825 free(buf);
1826 return LY_EVALID;
1827 }
1828 *fracdig = num;
1829 free(buf);
1830
Radek Krejci6d6556c2018-11-08 09:37:45 +01001831 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001832 switch (kw) {
1833 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001834 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001835 break;
1836 default:
David Sedlákb3077192019-06-19 10:55:37 +02001837 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001838 return LY_EVALID;
1839 }
1840 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001841 return ret;
1842}
1843
Michal Vaskoea5abea2018-09-18 13:10:54 +02001844/**
1845 * @brief Parse the require-instance statement. Substatement of type statement.
1846 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001847 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001848 * @param[in,out] data Data to read from, always moved to currently handled character.
1849 * @param[in,out] reqinst Value to write to.
1850 * @param[in,out] flags Flags to write to.
1851 * @param[in,out] exts Extension instances to add to.
1852 *
1853 * @return LY_ERR values.
1854 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001855static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001856parse_type_reqinstance(struct lys_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001857 struct lysp_ext_instance **exts)
1858{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001859 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001860 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001861 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001862 enum yang_keyword kw;
1863
1864 if (*flags & LYS_SET_REQINST) {
David Sedlákb3077192019-06-19 10:55:37 +02001865 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001866 return LY_EVALID;
1867 }
1868 *flags |= LYS_SET_REQINST;
1869
1870 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001871 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001872
1873 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1874 *reqinst = 1;
1875 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02001876 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001877 free(buf);
1878 return LY_EVALID;
1879 }
1880 free(buf);
1881
Radek Krejci6d6556c2018-11-08 09:37:45 +01001882 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001883 switch (kw) {
1884 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001885 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001886 break;
1887 default:
David Sedlákb3077192019-06-19 10:55:37 +02001888 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001889 return LY_EVALID;
1890 }
1891 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001892 return ret;
1893}
1894
Michal Vaskoea5abea2018-09-18 13:10:54 +02001895/**
1896 * @brief Parse the modifier statement. Substatement of type pattern statement.
1897 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001898 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001899 * @param[in,out] data Data to read from, always moved to currently handled character.
1900 * @param[in,out] pat Value to write to.
1901 * @param[in,out] exts Extension instances to add to.
1902 *
1903 * @return LY_ERR values.
1904 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001905static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001906parse_type_pattern_modifier(struct lys_parser_ctx *ctx, const char **data, const char **pat, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001907{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001908 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001909 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001910 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001911 enum yang_keyword kw;
1912
1913 if ((*pat)[0] == 0x15) {
David Sedlákb3077192019-06-19 10:55:37 +02001914 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001915 return LY_EVALID;
1916 }
1917
1918 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001919 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001920
1921 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02001922 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001923 free(buf);
1924 return LY_EVALID;
1925 }
1926 free(buf);
1927
1928 /* replace the value in the dictionary */
1929 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001930 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001931 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001932 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001933
1934 assert(buf[0] == 0x06);
1935 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02001936 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001937
Radek Krejci6d6556c2018-11-08 09:37:45 +01001938 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001939 switch (kw) {
1940 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001941 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001942 break;
1943 default:
David Sedlákb3077192019-06-19 10:55:37 +02001944 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001945 return LY_EVALID;
1946 }
1947 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001948 return ret;
1949}
1950
Michal Vaskoea5abea2018-09-18 13:10:54 +02001951/**
1952 * @brief Parse the pattern statement. Substatement of type statement.
1953 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001954 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001955 * @param[in,out] data Data to read from, always moved to currently handled character.
1956 * @param[in,out] patterns Restrictions to add to.
1957 *
1958 * @return LY_ERR values.
1959 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001960static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001961parse_type_pattern(struct lys_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001962{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001963 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001964 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001965 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001966 enum yang_keyword kw;
1967 struct lysp_restr *restr;
1968
Radek Krejci2c4e7172018-10-19 15:56:26 +02001969 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001970
1971 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001972 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001973
1974 /* add special meaning first byte */
1975 if (buf) {
1976 buf = realloc(buf, word_len + 2);
1977 word = buf;
1978 } else {
1979 buf = malloc(word_len + 2);
1980 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001981 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02001982 memmove(buf + 1, word, word_len);
1983 buf[0] = 0x06; /* pattern's default regular-match flag */
1984 buf[word_len + 1] = '\0'; /* terminating NULL byte */
1985 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001986
Radek Krejci6d6556c2018-11-08 09:37:45 +01001987 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001988 switch (kw) {
1989 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001990 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001991 break;
1992 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001993 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001994 break;
1995 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001996 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001997 break;
1998 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001999 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002000 break;
2001 case YANG_MODIFIER:
Radek Krejciceaf2122019-01-02 15:03:26 +01002002 YANG_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002003 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002004 break;
2005 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002006 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002007 break;
2008 default:
David Sedlákb3077192019-06-19 10:55:37 +02002009 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002010 return LY_EVALID;
2011 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002012 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002013 return ret;
2014}
2015
Michal Vaskoea5abea2018-09-18 13:10:54 +02002016/**
2017 * @brief Parse the type statement.
2018 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002019 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002020 * @param[in,out] data Data to read from, always moved to currently handled character.
2021 * @param[in,out] type Type to wrote to.
2022 *
2023 * @return LY_ERR values.
2024 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002025static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002026parse_type(struct lys_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002027{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002028 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002029 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002030 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002031 enum yang_keyword kw;
2032 struct lysp_type *nest_type;
2033
2034 if (type->name) {
David Sedlákb3077192019-06-19 10:55:37 +02002035 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002036 return LY_EVALID;
2037 }
2038
2039 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002040 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002041 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002042
Radek Krejci6d6556c2018-11-08 09:37:45 +01002043 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002044 switch (kw) {
2045 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002046 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002047 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002048 break;
2049 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002050 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002051 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002052 break;
2053 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002054 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002055 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002056 break;
2057 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002058 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002059 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002060 break;
2061 case YANG_LENGTH:
2062 if (type->length) {
David Sedlákb3077192019-06-19 10:55:37 +02002063 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002064 return LY_EVALID;
2065 }
2066 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002067 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002068
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002069 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002070 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002071 break;
2072 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002073 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002074 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002075 break;
2076 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002077 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002078 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002079 break;
2080 case YANG_RANGE:
2081 if (type->range) {
David Sedlákb3077192019-06-19 10:55:37 +02002082 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002083 return LY_EVALID;
2084 }
2085 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002086 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002087
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002088 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002089 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002090 break;
2091 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002092 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002093 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002094 break;
2095 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002096 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2097 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002098 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002099 break;
2100 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002101 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002102 break;
2103 default:
David Sedlákb3077192019-06-19 10:55:37 +02002104 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002105 return LY_EVALID;
2106 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002107 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002108 return ret;
2109}
2110
Michal Vaskoea5abea2018-09-18 13:10:54 +02002111/**
2112 * @brief Parse the leaf statement.
2113 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002114 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002115 * @param[in,out] data Data to read from, always moved to currently handled character.
2116 * @param[in,out] siblings Siblings to add to.
2117 *
2118 * @return LY_ERR values.
2119 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002120LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002121parse_leaf(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002122{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002123 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002124 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002125 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002126 enum yang_keyword kw;
2127 struct lysp_node *iter;
2128 struct lysp_node_leaf *leaf;
2129
2130 /* create structure */
2131 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002132 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002133 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002134 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002135
2136 /* insert into siblings */
2137 if (!*siblings) {
2138 *siblings = (struct lysp_node *)leaf;
2139 } else {
2140 for (iter = *siblings; iter->next; iter = iter->next);
2141 iter->next = (struct lysp_node *)leaf;
2142 }
2143
2144 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002145 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002146 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002147
2148 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002149 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002150 switch (kw) {
2151 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002152 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002153 break;
2154 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002155 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002156 break;
2157 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002158 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002159 break;
2160 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002161 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002162 break;
2163 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002164 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002165 break;
2166 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002167 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002168 break;
2169 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002170 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002171 break;
2172 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002173 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002174 break;
2175 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002176 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002177 break;
2178 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002179 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002180 break;
2181 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002182 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002183 break;
2184 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002185 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002186 break;
2187 default:
David Sedlákb3077192019-06-19 10:55:37 +02002188 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189 return LY_EVALID;
2190 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002191 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002192 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002193checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002194 /* mandatory substatements */
2195 if (!leaf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002196 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002197 return LY_EVALID;
2198 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002199 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
David Sedlákb3077192019-06-19 10:55:37 +02002200 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002201 return LY_EVALID;
2202 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002203
2204 return ret;
2205}
2206
Michal Vaskoea5abea2018-09-18 13:10:54 +02002207/**
2208 * @brief Parse the max-elements statement.
2209 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002210 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002211 * @param[in,out] data Data to read from, always moved to currently handled character.
2212 * @param[in,out] max Value to write to.
2213 * @param[in,out] flags Flags to write to.
2214 * @param[in,out] exts Extension instances to add to.
2215 *
2216 * @return LY_ERR values.
2217 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002218LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002219parse_maxelements(struct lys_parser_ctx *ctx, const char **data, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002220{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002221 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002222 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002223 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002224 unsigned long int num;
2225 enum yang_keyword kw;
2226
2227 if (*flags & LYS_SET_MAX) {
David Sedlákb3077192019-06-19 10:55:37 +02002228 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002229 return LY_EVALID;
2230 }
2231 *flags |= LYS_SET_MAX;
2232
2233 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002234 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002235
2236 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
David Sedlákb3077192019-06-19 10:55:37 +02002237 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002238 free(buf);
2239 return LY_EVALID;
2240 }
2241
2242 if (strncmp(word, "unbounded", word_len)) {
2243 errno = 0;
2244 num = strtoul(word, &ptr, 10);
2245 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002246 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002247 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002248 free(buf);
2249 return LY_EVALID;
2250 }
2251 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002252 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002253 free(buf);
2254 return LY_EVALID;
2255 }
2256
2257 *max = num;
2258 }
2259 free(buf);
2260
Radek Krejci6d6556c2018-11-08 09:37:45 +01002261 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002262 switch (kw) {
2263 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002264 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002265 break;
2266 default:
David Sedlákb3077192019-06-19 10:55:37 +02002267 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002268 return LY_EVALID;
2269 }
2270 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002271 return ret;
2272}
2273
Michal Vaskoea5abea2018-09-18 13:10:54 +02002274/**
2275 * @brief Parse the min-elements statement.
2276 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002277 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002278 * @param[in,out] data Data to read from, always moved to currently handled character.
2279 * @param[in,out] min Value to write to.
2280 * @param[in,out] flags Flags to write to.
2281 * @param[in,out] exts Extension instances to add to.
2282 *
2283 * @return LY_ERR values.
2284 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002285LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002286parse_minelements(struct lys_parser_ctx *ctx, const char **data, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002287{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002288 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002289 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002290 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002291 unsigned long int num;
2292 enum yang_keyword kw;
2293
2294 if (*flags & LYS_SET_MIN) {
David Sedlákb3077192019-06-19 10:55:37 +02002295 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002296 return LY_EVALID;
2297 }
2298 *flags |= LYS_SET_MIN;
2299
2300 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002301 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002302
2303 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
David Sedlákb3077192019-06-19 10:55:37 +02002304 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002305 free(buf);
2306 return LY_EVALID;
2307 }
2308
2309 errno = 0;
2310 num = strtoul(word, &ptr, 10);
2311 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002312 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002313 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002314 free(buf);
2315 return LY_EVALID;
2316 }
2317 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002318 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002319 free(buf);
2320 return LY_EVALID;
2321 }
2322 *min = num;
2323 free(buf);
2324
Radek Krejci6d6556c2018-11-08 09:37:45 +01002325 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002326 switch (kw) {
2327 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002328 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002329 break;
2330 default:
David Sedlákb3077192019-06-19 10:55:37 +02002331 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002332 return LY_EVALID;
2333 }
2334 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002335 return ret;
2336}
2337
Michal Vaskoea5abea2018-09-18 13:10:54 +02002338/**
2339 * @brief Parse the ordered-by statement.
2340 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002341 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002342 * @param[in,out] data Data to read from, always moved to currently handled character.
2343 * @param[in,out] flags Flags to write to.
2344 * @param[in,out] exts Extension instances to add to.
2345 *
2346 * @return LY_ERR values.
2347 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002348static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002349parse_orderedby(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002350{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002351 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002352 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002353 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002354 enum yang_keyword kw;
2355
2356 if (*flags & LYS_ORDBY_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02002357 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002358 return LY_EVALID;
2359 }
2360
2361 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002362 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002363
2364 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2365 *flags |= LYS_ORDBY_SYSTEM;
2366 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2367 *flags |= LYS_ORDBY_USER;
2368 } else {
David Sedlákb3077192019-06-19 10:55:37 +02002369 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002370 free(buf);
2371 return LY_EVALID;
2372 }
2373 free(buf);
2374
Radek Krejci6d6556c2018-11-08 09:37:45 +01002375 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002376 switch (kw) {
2377 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002378 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002379 break;
2380 default:
David Sedlákb3077192019-06-19 10:55:37 +02002381 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002382 return LY_EVALID;
2383 }
2384 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002385 return ret;
2386}
2387
Michal Vaskoea5abea2018-09-18 13:10:54 +02002388/**
2389 * @brief Parse the leaf-list statement.
2390 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002391 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002392 * @param[in,out] data Data to read from, always moved to currently handled character.
2393 * @param[in,out] siblings Siblings to add to.
2394 *
2395 * @return LY_ERR values.
2396 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002397LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002398parse_leaflist(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002399{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002400 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002401 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002402 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002403 enum yang_keyword kw;
2404 struct lysp_node *iter;
2405 struct lysp_node_leaflist *llist;
2406
2407 /* create structure */
2408 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002409 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002410 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002411 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002412
2413 /* insert into siblings */
2414 if (!*siblings) {
2415 *siblings = (struct lysp_node *)llist;
2416 } else {
2417 for (iter = *siblings; iter->next; iter = iter->next);
2418 iter->next = (struct lysp_node *)llist;
2419 }
2420
2421 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002422 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002423 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002424
2425 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002426 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002427 switch (kw) {
2428 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002429 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002430 break;
2431 case YANG_DEFAULT:
Radek Krejciceaf2122019-01-02 15:03:26 +01002432 YANG_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002433 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002434 break;
2435 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002436 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002437 break;
2438 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002439 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002440 break;
2441 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002442 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002443 break;
2444 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002445 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002446 break;
2447 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002448 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002449 break;
2450 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002451 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002452 break;
2453 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002454 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002455 break;
2456 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002457 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002458 break;
2459 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002460 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002461 break;
2462 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002463 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002464 break;
2465 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002466 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002467 break;
2468 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002469 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002470 break;
2471 default:
David Sedlákb3077192019-06-19 10:55:37 +02002472 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002473 return LY_EVALID;
2474 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002475 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002476 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002477checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002478 /* mandatory substatements */
2479 if (!llist->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002480 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002481 return LY_EVALID;
2482 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002483 if ((llist->min) && (llist->dflts)) {
David Sedlákb3077192019-06-19 10:55:37 +02002484 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
Radek Krejci0e5d8382018-11-28 16:37:53 +01002485 return LY_EVALID;
2486 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002487 if (llist->max && llist->min > llist->max) {
David Sedlákb3077192019-06-19 10:55:37 +02002488 LOGVAL_PARSER(ctx, LYVE_SEMANTICS,
Radek Krejcidf6cad12018-11-28 17:10:55 +01002489 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2490 llist->min, llist->max);
2491 return LY_EVALID;
2492 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002493
2494 return ret;
2495}
2496
Michal Vaskoea5abea2018-09-18 13:10:54 +02002497/**
2498 * @brief Parse the refine statement.
2499 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002500 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002501 * @param[in,out] data Data to read from, always moved to currently handled character.
2502 * @param[in,out] refines Refines to add to.
2503 *
2504 * @return LY_ERR values.
2505 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002506static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002507parse_refine(struct lys_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002508{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002509 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002510 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002511 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002512 enum yang_keyword kw;
2513 struct lysp_refine *rf;
2514
Radek Krejci2c4e7172018-10-19 15:56:26 +02002515 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002516
2517 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002518 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejcif09e4e82019-06-14 15:08:11 +02002519 YANG_CHECK_NONEMPTY(ctx, NULL, word_len, "refine");
Radek Krejci44ceedc2018-10-02 15:54:31 +02002520 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002521
Radek Krejci6d6556c2018-11-08 09:37:45 +01002522 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002523 switch (kw) {
2524 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002525 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002526 break;
2527 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002528 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002529 break;
2530 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002531 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002532 break;
2533 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01002534 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002535 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002536 break;
2537 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002538 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002539 break;
2540 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002541 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002542 break;
2543 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002544 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002545 break;
2546 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002547 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002548 break;
2549 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002550 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002551 break;
2552 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002553 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002554 break;
2555 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002556 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002557 break;
2558 default:
David Sedlákb3077192019-06-19 10:55:37 +02002559 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002560 return LY_EVALID;
2561 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002562 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002563 return ret;
2564}
2565
Michal Vaskoea5abea2018-09-18 13:10:54 +02002566/**
2567 * @brief Parse the typedef statement.
2568 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002569 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002570 * @param[in,out] data Data to read from, always moved to currently handled character.
2571 * @param[in,out] typedefs Typedefs to add to.
2572 *
2573 * @return LY_ERR values.
2574 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002575static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002576parse_typedef(struct lys_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002577{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002578 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002579 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002580 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002581 enum yang_keyword kw;
2582 struct lysp_tpdf *tpdf;
2583
Radek Krejci2c4e7172018-10-19 15:56:26 +02002584 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002585
2586 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002587 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002588 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002589
2590 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002591 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002592 switch (kw) {
2593 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002594 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002595 break;
2596 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002597 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002598 break;
2599 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002600 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002601 break;
2602 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002603 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002604 break;
2605 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002606 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002607 break;
2608 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002609 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002610 break;
2611 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002612 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002613 break;
2614 default:
David Sedlákb3077192019-06-19 10:55:37 +02002615 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002616 return LY_EVALID;
2617 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002618 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002619 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002620checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002621 /* mandatory substatements */
2622 if (!tpdf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002623 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002624 return LY_EVALID;
2625 }
2626
Radek Krejcibbe09a92018-11-08 09:36:54 +01002627 /* store data for collision check */
Radek Krejci7fc68292019-06-12 13:51:09 +02002628 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01002629 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2630 }
2631
Michal Vasko7fbc8162018-09-17 10:35:16 +02002632 return ret;
2633}
2634
Michal Vaskoea5abea2018-09-18 13:10:54 +02002635/**
2636 * @brief Parse the input or output statement.
2637 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002638 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002639 * @param[in,out] data Data to read from, always moved to currently handled character.
2640 * @param[in] kw Type of this particular keyword
2641 * @param[in,out] inout_p Input/output pointer to write to.
2642 *
2643 * @return LY_ERR values.
2644 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002645static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002646parse_inout(struct lys_parser_ctx *ctx, const char **data, enum yang_keyword inout_kw, struct lysp_node *parent, struct lysp_action_inout *inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002647{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002648 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002649 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002650 size_t word_len;
Radek Krejci10113652018-11-14 16:56:50 +01002651 enum yang_keyword kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002652
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002653 if (inout_p->nodetype) {
David Sedlákb3077192019-06-19 10:55:37 +02002654 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002655 return LY_EVALID;
2656 }
2657
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002658 /* initiate structure */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002659 inout_p->nodetype = &((struct lysp_action*)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002660 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002661
2662 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02002663 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002664 switch (kw) {
2665 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002666 YANG_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci10113652018-11-14 16:56:50 +01002667 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002668 case YANG_ANYXML:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002669 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002670 break;
2671 case YANG_CHOICE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002672 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002673 break;
2674 case YANG_CONTAINER:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002675 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002676 break;
2677 case YANG_LEAF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002678 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002679 break;
2680 case YANG_LEAF_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002681 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002682 break;
2683 case YANG_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002684 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002685 break;
2686 case YANG_USES:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002687 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002688 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002689 case YANG_TYPEDEF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002690 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002691 break;
2692 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01002693 YANG_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002694 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002695 break;
2696 case YANG_GROUPING:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002697 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002698 break;
2699 case YANG_CUSTOM:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002700 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002701 break;
2702 default:
David Sedlákb3077192019-06-19 10:55:37 +02002703 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002704 return LY_EVALID;
2705 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002706 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002707 LY_CHECK_RET(ret);
2708checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002709 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02002710 LY_CHECK_RET(parse_finalize_reallocated(ctx, inout_p->groupings, NULL, NULL, NULL));
2711
Michal Vasko7fbc8162018-09-17 10:35:16 +02002712 return ret;
2713}
2714
Michal Vaskoea5abea2018-09-18 13:10:54 +02002715/**
2716 * @brief Parse the action statement.
2717 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002718 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002719 * @param[in,out] data Data to read from, always moved to currently handled character.
2720 * @param[in,out] actions Actions to add to.
2721 *
2722 * @return LY_ERR values.
2723 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002724LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002725parse_action(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002726{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002727 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002728 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002729 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002730 enum yang_keyword kw;
2731 struct lysp_action *act;
2732
Radek Krejci2c4e7172018-10-19 15:56:26 +02002733 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002734
2735 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002736 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002737 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002738 act->nodetype = LYS_ACTION;
2739 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002740
Radek Krejci7fc68292019-06-12 13:51:09 +02002741 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002742 switch (kw) {
2743 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002744 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002745 break;
2746 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002747 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002748 break;
2749 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002750 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002751 break;
2752 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002753 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002754 break;
2755
2756 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002757 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002758 break;
2759 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002760 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002761 break;
2762
2763 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002764 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002765 break;
2766 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002767 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002768 break;
2769 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002770 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002771 break;
2772 default:
David Sedlákb3077192019-06-19 10:55:37 +02002773 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002774 return LY_EVALID;
2775 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002776 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002777 LY_CHECK_RET(ret);
2778checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002779 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02002780 LY_CHECK_RET(parse_finalize_reallocated(ctx, act->groupings, NULL, NULL, NULL));
2781
Michal Vasko7fbc8162018-09-17 10:35:16 +02002782 return ret;
2783}
2784
Michal Vaskoea5abea2018-09-18 13:10:54 +02002785/**
2786 * @brief Parse the notification statement.
2787 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002788 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002789 * @param[in,out] data Data to read from, always moved to currently handled character.
2790 * @param[in,out] notifs Notifications to add to.
2791 *
2792 * @return LY_ERR values.
2793 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002794LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002795parse_notif(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002797 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002798 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002799 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002800 enum yang_keyword kw;
2801 struct lysp_notif *notif;
2802
Radek Krejci2c4e7172018-10-19 15:56:26 +02002803 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002804
2805 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002806 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002807 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002808 notif->nodetype = LYS_NOTIF;
2809 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002810
Radek Krejci7fc68292019-06-12 13:51:09 +02002811 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002812 switch (kw) {
2813 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002814 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002815 break;
2816 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002817 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002818 break;
2819 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002820 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002821 break;
2822 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002823 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002824 break;
2825
2826 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002827 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci10113652018-11-14 16:56:50 +01002828 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002829 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002830 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002831 break;
2832 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002833 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002834 break;
2835 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002836 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002837 break;
2838 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002839 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002840 break;
2841 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002842 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002843 break;
2844 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002845 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002846 break;
2847 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002848 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002849 break;
2850
2851 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01002852 YANG_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002853 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002854 break;
2855 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002856 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 break;
2858 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002859 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860 break;
2861 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002862 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863 break;
2864 default:
David Sedlákb3077192019-06-19 10:55:37 +02002865 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002866 return LY_EVALID;
2867 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002868 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002869 LY_CHECK_RET(ret);
2870checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002871 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02002872 LY_CHECK_RET(parse_finalize_reallocated(ctx, notif->groupings, NULL, NULL, NULL));
2873
Michal Vasko7fbc8162018-09-17 10:35:16 +02002874 return ret;
2875}
2876
Michal Vaskoea5abea2018-09-18 13:10:54 +02002877/**
2878 * @brief Parse the grouping statement.
2879 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002880 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002881 * @param[in,out] data Data to read from, always moved to currently handled character.
2882 * @param[in,out] groupings Groupings to add to.
2883 *
2884 * @return LY_ERR values.
2885 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002886LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002887parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002888{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002889 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002890 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002891 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002892 enum yang_keyword kw;
2893 struct lysp_grp *grp;
2894
Radek Krejci2c4e7172018-10-19 15:56:26 +02002895 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002896
2897 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002898 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002899 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002900 grp->nodetype = LYS_GROUPING;
2901 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002902
Radek Krejci7fc68292019-06-12 13:51:09 +02002903 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002904 switch (kw) {
2905 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002906 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002907 break;
2908 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002909 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002910 break;
2911 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002912 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002913 break;
2914
2915 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002916 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci10113652018-11-14 16:56:50 +01002917 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002918 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002919 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002920 break;
2921 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002922 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002923 break;
2924 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002925 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002926 break;
2927 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002928 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002929 break;
2930 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002931 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002932 break;
2933 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002934 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002935 break;
2936 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002937 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002938 break;
2939
2940 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002941 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002942 break;
2943 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01002944 YANG_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002945 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002946 break;
2947 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002948 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002949 break;
2950 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01002951 YANG_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002952 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002953 break;
2954 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002955 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002956 break;
2957 default:
David Sedlákb3077192019-06-19 10:55:37 +02002958 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002959 return LY_EVALID;
2960 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002961 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002962 LY_CHECK_RET(ret);
2963checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002964 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02002965 LY_CHECK_RET(parse_finalize_reallocated(ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2966
Michal Vasko7fbc8162018-09-17 10:35:16 +02002967 return ret;
2968}
2969
Michal Vaskoea5abea2018-09-18 13:10:54 +02002970/**
2971 * @brief Parse the refine statement.
2972 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002973 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002974 * @param[in,out] data Data to read from, always moved to currently handled character.
2975 * @param[in,out] augments Augments to add to.
2976 *
2977 * @return LY_ERR values.
2978 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002979LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002980parse_augment(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002981{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002982 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002983 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002984 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002985 enum yang_keyword kw;
2986 struct lysp_augment *aug;
2987
Radek Krejci2c4e7172018-10-19 15:56:26 +02002988 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002989
2990 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002991 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejcif09e4e82019-06-14 15:08:11 +02002992 YANG_CHECK_NONEMPTY(ctx, NULL, word_len, "augment");
Radek Krejci44ceedc2018-10-02 15:54:31 +02002993 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002994 aug->nodetype = LYS_AUGMENT;
2995 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002996
Radek Krejci7fc68292019-06-12 13:51:09 +02002997 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002998 switch (kw) {
2999 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003000 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003001 break;
3002 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003003 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003004 break;
3005 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003006 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003007 break;
3008 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003009 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003010 break;
3011 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003012 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003013 break;
3014
3015 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003016 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci10113652018-11-14 16:56:50 +01003017 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003018 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003019 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003020 break;
3021 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003022 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003023 break;
3024 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003025 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003026 break;
3027 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003028 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003029 break;
3030 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003031 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032 break;
3033 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003034 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003035 break;
3036 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003037 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003038 break;
3039 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003040 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003041 break;
3042
3043 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003044 YANG_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003045 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003046 break;
3047 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003048 YANG_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003049 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003050 break;
3051 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003052 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003053 break;
3054 default:
David Sedlákb3077192019-06-19 10:55:37 +02003055 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003056 return LY_EVALID;
3057 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003058 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003059 LY_CHECK_RET(ret);
3060checks:
3061 /* finalize parent pointers to the reallocated items */
3062 LY_CHECK_RET(parse_finalize_reallocated(ctx, NULL, NULL, aug->actions, aug->notifs));
3063
Michal Vasko7fbc8162018-09-17 10:35:16 +02003064 return ret;
3065}
3066
Michal Vaskoea5abea2018-09-18 13:10:54 +02003067/**
Radek Krejci7fc68292019-06-12 13:51:09 +02003068 * @brief Finalize some of the structures in case they are stored in sized array,
3069 * which can be possibly reallocated and some other data may point to them.
3070 *
3071 * Update parent pointers in the nodes inside grouping/augment/RPC/Notification, which could be reallocated.
3072 *
3073 * @param[in] mod Parsed module to be updated.
3074 * @return LY_ERR value (currently only LY_SUCCESS, but it can change in future).
3075 */
3076static LY_ERR
3077parse_finalize_reallocated(struct lys_parser_ctx *ctx, struct lysp_grp *groupings, struct lysp_augment *augments,
3078 struct lysp_action *actions, struct lysp_notif *notifs)
3079{
3080 unsigned int u, v;
3081 struct lysp_node *child;
3082
3083 /* finalize parent pointers to the reallocated items */
3084
3085 /* gropings */
3086 LY_ARRAY_FOR(groupings, u) {
3087 LY_LIST_FOR(groupings[u].data, child) {
3088 child->parent = (struct lysp_node*)&groupings[u];
3089 }
3090 LY_ARRAY_FOR(groupings[u].actions, v) {
3091 groupings[u].actions[v].parent = (struct lysp_node*)&groupings[u];
3092 }
3093 LY_ARRAY_FOR(groupings[u].notifs, v) {
3094 groupings[u].notifs[v].parent = (struct lysp_node*)&groupings[u];
3095 }
3096 LY_ARRAY_FOR(groupings[u].groupings, v) {
3097 groupings[u].groupings[v].parent = (struct lysp_node*)&groupings[u];
3098 }
3099 if (groupings[u].typedefs) {
3100 ly_set_add(&ctx->tpdfs_nodes, &groupings[u], 0);
3101 }
3102 }
3103
3104 /* augments */
3105 LY_ARRAY_FOR(augments, u) {
3106 LY_LIST_FOR(augments[u].child, child) {
3107 child->parent = (struct lysp_node*)&augments[u];
3108 }
3109 LY_ARRAY_FOR(augments[u].actions, v) {
3110 augments[u].actions[v].parent = (struct lysp_node*)&augments[u];
3111 }
3112 LY_ARRAY_FOR(augments[u].notifs, v) {
3113 augments[u].notifs[v].parent = (struct lysp_node*)&augments[u];
3114 }
3115 }
3116
3117 /* actions */
3118 LY_ARRAY_FOR(actions, u) {
3119 if (actions[u].input.parent) {
3120 actions[u].input.parent = (struct lysp_node*)&actions[u];
3121 LY_LIST_FOR(actions[u].input.data, child) {
3122 child->parent = (struct lysp_node*)&actions[u].input;
3123 }
3124 LY_ARRAY_FOR(actions[u].input.groupings, v) {
3125 actions[u].input.groupings[v].parent = (struct lysp_node*)&actions[u].input;
3126 }
3127 if (actions[u].input.typedefs) {
3128 ly_set_add(&ctx->tpdfs_nodes, &actions[u].input, 0);
3129 }
3130 }
3131 if (actions[u].output.parent) {
3132 actions[u].output.parent = (struct lysp_node*)&actions[u];
3133 LY_LIST_FOR(actions[u].output.data, child) {
3134 child->parent = (struct lysp_node*)&actions[u].output;
3135 }
3136 LY_ARRAY_FOR(actions[u].output.groupings, v) {
3137 actions[u].output.groupings[v].parent = (struct lysp_node*)&actions[u].output;
3138 }
3139 if (actions[u].output.typedefs) {
3140 ly_set_add(&ctx->tpdfs_nodes, &actions[u].output, 0);
3141 }
3142 }
3143 LY_ARRAY_FOR(actions[u].groupings, v) {
3144 actions[u].groupings[v].parent = (struct lysp_node*)&actions[u];
3145 }
3146 if (actions[u].typedefs) {
3147 ly_set_add(&ctx->tpdfs_nodes, &actions[u], 0);
3148 }
3149 }
3150
3151 /* notifications */
3152 LY_ARRAY_FOR(notifs, u) {
3153 LY_LIST_FOR(notifs[u].data, child) {
3154 child->parent = (struct lysp_node*)&notifs[u];
3155 }
3156 LY_ARRAY_FOR(notifs[u].groupings, v) {
3157 notifs[u].groupings[v].parent = (struct lysp_node*)&notifs[u];
3158 }
3159 if (notifs[u].typedefs) {
3160 ly_set_add(&ctx->tpdfs_nodes, &notifs[u], 0);
3161 }
3162 }
3163
3164 return LY_SUCCESS;
3165}
3166
3167/**
Michal Vaskoea5abea2018-09-18 13:10:54 +02003168 * @brief Parse the uses statement.
3169 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003170 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003171 * @param[in,out] data Data to read from, always moved to currently handled character.
3172 * @param[in,out] siblings Siblings to add to.
3173 *
3174 * @return LY_ERR values.
3175 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003176LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003177parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003178{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003179 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003180 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003181 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003182 enum yang_keyword kw;
3183 struct lysp_node *iter;
3184 struct lysp_node_uses *uses;
3185
3186 /* create structure */
3187 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003188 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003189 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003190 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003191
3192 /* insert into siblings */
3193 if (!*siblings) {
3194 *siblings = (struct lysp_node *)uses;
3195 } else {
3196 for (iter = *siblings; iter->next; iter = iter->next);
3197 iter->next = (struct lysp_node *)uses;
3198 }
3199
3200 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003201 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003202 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003203
3204 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003205 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003206 switch (kw) {
3207 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003208 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003209 break;
3210 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003211 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003212 break;
3213 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003214 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003215 break;
3216 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003217 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003218 break;
3219 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003220 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003221 break;
3222
3223 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003224 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003225 break;
3226 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003227 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003228 break;
3229 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003230 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003231 break;
3232 default:
David Sedlákb3077192019-06-19 10:55:37 +02003233 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003234 return LY_EVALID;
3235 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003236 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003237checks:
3238 /* finalize parent pointers to the reallocated items */
3239 LY_CHECK_RET(parse_finalize_reallocated(ctx, NULL, uses->augments, NULL, NULL));
3240
Michal Vasko7fbc8162018-09-17 10:35:16 +02003241 return ret;
3242}
3243
Michal Vaskoea5abea2018-09-18 13:10:54 +02003244/**
3245 * @brief Parse the case statement.
3246 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003247 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003248 * @param[in,out] data Data to read from, always moved to currently handled character.
3249 * @param[in,out] siblings Siblings to add to.
3250 *
3251 * @return LY_ERR values.
3252 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003253LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003254parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003255{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003256 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003257 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003258 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003259 enum yang_keyword kw;
3260 struct lysp_node *iter;
3261 struct lysp_node_case *cas;
3262
3263 /* create structure */
3264 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003265 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003266 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003267 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003268
3269 /* insert into siblings */
3270 if (!*siblings) {
3271 *siblings = (struct lysp_node *)cas;
3272 } else {
3273 for (iter = *siblings; iter->next; iter = iter->next);
3274 iter->next = (struct lysp_node *)cas;
3275 }
3276
3277 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003278 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003279 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003280
3281 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003282 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003283 switch (kw) {
3284 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003285 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003286 break;
3287 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003288 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003289 break;
3290 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003291 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003292 break;
3293 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003294 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003295 break;
3296 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003297 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003298 break;
3299
3300 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003301 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci10113652018-11-14 16:56:50 +01003302 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003303 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003304 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003305 break;
3306 case YANG_CHOICE:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003307 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003308 break;
3309 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003310 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003311 break;
3312 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003313 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003314 break;
3315 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003316 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003317 break;
3318 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003319 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003320 break;
3321 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003322 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003323 break;
3324 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003325 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003326 break;
3327 default:
David Sedlákb3077192019-06-19 10:55:37 +02003328 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003329 return LY_EVALID;
3330 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003331 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003332 return ret;
3333}
3334
Michal Vaskoea5abea2018-09-18 13:10:54 +02003335/**
3336 * @brief Parse the choice statement.
3337 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003338 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003339 * @param[in,out] data Data to read from, always moved to currently handled character.
3340 * @param[in,out] siblings Siblings to add to.
3341 *
3342 * @return LY_ERR values.
3343 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003344LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003345parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003346{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003347 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003348 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003349 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003350 enum yang_keyword kw;
3351 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003352 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003353
3354 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003355 choice = calloc(1, sizeof *choice);
3356 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3357 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003358 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003359
3360 /* insert into siblings */
3361 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003362 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003363 } else {
3364 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003365 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003366 }
3367
3368 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003369 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003370 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003371
3372 /* parse substatements */
Radek Krejcia9026eb2018-12-12 16:04:47 +01003373 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003374 switch (kw) {
3375 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003376 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003377 break;
3378 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003379 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003380 break;
3381 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003382 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003383 break;
3384 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003385 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003386 break;
3387 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003388 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003389 break;
3390 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003391 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003392 break;
3393 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003394 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003395 break;
3396 case YANG_DEFAULT:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003397 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_PREF_IDENTIF_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003398 break;
3399
3400 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003401 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci10113652018-11-14 16:56:50 +01003402 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003403 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003404 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003405 break;
3406 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003407 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003408 break;
3409 case YANG_CHOICE:
Radek Krejciceaf2122019-01-02 15:03:26 +01003410 YANG_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003411 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003412 break;
3413 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003414 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003415 break;
3416 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003417 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003418 break;
3419 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003420 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003421 break;
3422 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003423 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003424 break;
3425 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003426 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003427 break;
3428 default:
David Sedlákb3077192019-06-19 10:55:37 +02003429 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003430 return LY_EVALID;
3431 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003432 }
Radek Krejcia9026eb2018-12-12 16:04:47 +01003433 LY_CHECK_RET(ret);
3434checks:
3435 if ((choice->flags & LYS_MAND_TRUE) && choice->dflt) {
David Sedlákb3077192019-06-19 10:55:37 +02003436 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "choice");
Radek Krejcia9026eb2018-12-12 16:04:47 +01003437 return LY_EVALID;
3438 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003439 return ret;
3440}
3441
Michal Vaskoea5abea2018-09-18 13:10:54 +02003442/**
3443 * @brief Parse the container statement.
3444 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003445 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003446 * @param[in,out] data Data to read from, always moved to currently handled character.
3447 * @param[in,out] siblings Siblings to add to.
3448 *
3449 * @return LY_ERR values.
3450 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003451LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003452parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003453{
3454 LY_ERR ret = 0;
3455 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003456 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003457 enum yang_keyword kw;
3458 struct lysp_node *iter;
3459 struct lysp_node_container *cont;
3460
3461 /* create structure */
3462 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003463 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003464 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003465 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003466
3467 /* insert into siblings */
3468 if (!*siblings) {
3469 *siblings = (struct lysp_node *)cont;
3470 } else {
3471 for (iter = *siblings; iter->next; iter = iter->next);
3472 iter->next = (struct lysp_node *)cont;
3473 }
3474
3475 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003476 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003477 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003478
3479 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003480 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003481 switch (kw) {
3482 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003483 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003484 break;
3485 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003486 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003487 break;
3488 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003489 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003490 break;
3491 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003492 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003493 break;
3494 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003495 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003496 break;
3497 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003498 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003499 break;
3500 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003501 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003502 break;
3503
3504 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003505 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci10113652018-11-14 16:56:50 +01003506 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003507 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003508 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003509 break;
3510 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003511 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003512 break;
3513 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003514 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003515 break;
3516 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003517 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003518 break;
3519 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003520 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003521 break;
3522 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003523 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003524 break;
3525 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003526 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003527 break;
3528
3529 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003530 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003531 break;
3532 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003533 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003534 break;
3535 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003536 YANG_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003537 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003538 break;
3539 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003540 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003541 break;
3542 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003543 YANG_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003544 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003545 break;
3546 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003547 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003548 break;
3549 default:
David Sedlákb3077192019-06-19 10:55:37 +02003550 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003551 return LY_EVALID;
3552 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003553 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003554checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003555 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02003556 LY_CHECK_RET(parse_finalize_reallocated(ctx, cont->groupings, NULL, cont->actions, cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003557 return ret;
3558}
3559
Michal Vaskoea5abea2018-09-18 13:10:54 +02003560/**
3561 * @brief Parse the list statement.
3562 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003563 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003564 * @param[in,out] data Data to read from, always moved to currently handled character.
3565 * @param[in,out] siblings Siblings to add to.
3566 *
3567 * @return LY_ERR values.
3568 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003569LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003570parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003571{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003572 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003573 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003574 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003575 enum yang_keyword kw;
3576 struct lysp_node *iter;
3577 struct lysp_node_list *list;
3578
3579 /* create structure */
3580 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003581 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003582 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003583 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584
3585 /* insert into siblings */
3586 if (!*siblings) {
3587 *siblings = (struct lysp_node *)list;
3588 } else {
3589 for (iter = *siblings; iter->next; iter = iter->next);
3590 iter->next = (struct lysp_node *)list;
3591 }
3592
3593 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003594 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003595 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003596
3597 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003598 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003599 switch (kw) {
3600 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003601 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003602 break;
3603 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003604 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003605 break;
3606 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003607 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003608 break;
3609 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003610 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003611 break;
3612 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003613 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003614 break;
3615 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003616 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003617 break;
3618 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003619 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003620 break;
3621 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003622 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003623 break;
3624 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003625 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003626 break;
3627 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003628 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003629 break;
3630 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003631 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003632 break;
3633
3634 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003635 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci10113652018-11-14 16:56:50 +01003636 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003637 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003638 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003639 break;
3640 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003641 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003642 break;
3643 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003644 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003645 break;
3646 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003647 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003648 break;
3649 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003650 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003651 break;
3652 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003653 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003654 break;
3655 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003656 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003657 break;
3658
3659 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003660 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003661 break;
3662 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003663 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003664 break;
3665 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003666 YANG_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003667 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003668 break;
3669 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003670 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003671 break;
3672 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003673 YANG_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003674 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003675 break;
3676 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003677 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003678 break;
3679 default:
David Sedlákb3077192019-06-19 10:55:37 +02003680 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003681 return LY_EVALID;
3682 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003683 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003684 LY_CHECK_RET(ret);
3685checks:
Radek Krejci7fc68292019-06-12 13:51:09 +02003686 /* finalize parent pointers to the reallocated items */
3687 LY_CHECK_RET(parse_finalize_reallocated(ctx, list->groupings, NULL, list->actions, list->notifs));
3688
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003689 if (list->max && list->min > list->max) {
David Sedlákb3077192019-06-19 10:55:37 +02003690 LOGVAL_PARSER(ctx, LYVE_SEMANTICS,
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003691 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3692 list->min, list->max);
3693 return LY_EVALID;
3694 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003695
3696 return ret;
3697}
3698
Michal Vaskoea5abea2018-09-18 13:10:54 +02003699/**
3700 * @brief Parse the yin-element statement.
3701 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003702 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003703 * @param[in,out] data Data to read from, always moved to currently handled character.
3704 * @param[in,out] flags Flags to write to.
3705 * @param[in,out] exts Extension instances to add to.
3706 *
3707 * @return LY_ERR values.
3708 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003709static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003710parse_yinelement(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003711{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003712 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003713 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003714 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003715 enum yang_keyword kw;
3716
3717 if (*flags & LYS_YINELEM_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02003718 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003719 return LY_EVALID;
3720 }
3721
3722 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003723 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003724
3725 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3726 *flags |= LYS_YINELEM_TRUE;
3727 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3728 *flags |= LYS_YINELEM_FALSE;
3729 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003730 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003731 free(buf);
3732 return LY_EVALID;
3733 }
3734 free(buf);
3735
Radek Krejci6d6556c2018-11-08 09:37:45 +01003736 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003737 switch (kw) {
3738 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003739 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3740 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003741 default:
David Sedlákb3077192019-06-19 10:55:37 +02003742 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003743 return LY_EVALID;
3744 }
3745 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003746 return ret;
3747}
3748
Michal Vaskoea5abea2018-09-18 13:10:54 +02003749/**
David Sedlák2444f8f2019-07-09 11:02:47 +02003750 * @brief Parse the argument statement.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003751 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003752 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003753 * @param[in,out] data Data to read from, always moved to currently handled character.
3754 * @param[in,out] argument Value to write to.
3755 * @param[in,out] flags Flags to write to.
3756 * @param[in,out] exts Extension instances to add to.
3757 *
3758 * @return LY_ERR values.
3759 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003760static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003761parse_argument(struct lys_parser_ctx *ctx, const char **data, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003762{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003763 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003764 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003765 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003766 enum yang_keyword kw;
3767
3768 if (*argument) {
David Sedlákb3077192019-06-19 10:55:37 +02003769 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003770 return LY_EVALID;
3771 }
3772
3773 /* get value */
David Sedlák2444f8f2019-07-09 11:02:47 +02003774 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003775 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003776
Radek Krejci6d6556c2018-11-08 09:37:45 +01003777 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003778 switch (kw) {
3779 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003780 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003781 break;
3782 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003783 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003784 break;
3785 default:
David Sedlákb3077192019-06-19 10:55:37 +02003786 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003787 return LY_EVALID;
3788 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003789 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003790 return ret;
3791}
3792
Michal Vaskoea5abea2018-09-18 13:10:54 +02003793/**
3794 * @brief Parse the extension statement.
3795 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003796 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003797 * @param[in,out] data Data to read from, always moved to currently handled character.
3798 * @param[in,out] extensions Extensions to add to.
3799 *
3800 * @return LY_ERR values.
3801 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003802static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003803parse_extension(struct lys_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003804{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003805 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003806 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003807 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003808 enum yang_keyword kw;
3809 struct lysp_ext *ex;
3810
Radek Krejci2c4e7172018-10-19 15:56:26 +02003811 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003812
3813 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003814 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003815 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003816
Radek Krejci6d6556c2018-11-08 09:37:45 +01003817 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003818 switch (kw) {
3819 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003820 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003821 break;
3822 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003823 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003824 break;
3825 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003826 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003827 break;
3828 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003829 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003830 break;
3831 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003832 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003833 break;
3834 default:
David Sedlákb3077192019-06-19 10:55:37 +02003835 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003836 return LY_EVALID;
3837 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003838 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003839 return ret;
3840}
3841
Michal Vaskoea5abea2018-09-18 13:10:54 +02003842/**
3843 * @brief Parse the deviate statement.
3844 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003845 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003846 * @param[in,out] data Data to read from, always moved to currently handled character.
3847 * @param[in,out] deviates Deviates to add to.
3848 *
3849 * @return LY_ERR values.
3850 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003851LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003852parse_deviate(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003853{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003854 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003855 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003856 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003857 enum yang_keyword kw;
3858 struct lysp_deviate *iter, *d;
3859 struct lysp_deviate_add *d_add = NULL;
3860 struct lysp_deviate_rpl *d_rpl = NULL;
3861 struct lysp_deviate_del *d_del = NULL;
3862 const char **d_units, ***d_uniques, ***d_dflts;
3863 struct lysp_restr **d_musts;
3864 uint16_t *d_flags;
3865 uint32_t *d_min, *d_max;
3866
3867 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003868 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003869
3870 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3871 dev_mod = LYS_DEV_NOT_SUPPORTED;
3872 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3873 dev_mod = LYS_DEV_ADD;
3874 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3875 dev_mod = LYS_DEV_REPLACE;
3876 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3877 dev_mod = LYS_DEV_DELETE;
3878 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003879 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003880 free(buf);
3881 return LY_EVALID;
3882 }
3883 free(buf);
3884
3885 /* create structure */
3886 switch (dev_mod) {
3887 case LYS_DEV_NOT_SUPPORTED:
3888 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003889 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003890 break;
3891 case LYS_DEV_ADD:
3892 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003893 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003894 d = (struct lysp_deviate *)d_add;
3895 d_units = &d_add->units;
3896 d_uniques = &d_add->uniques;
3897 d_dflts = &d_add->dflts;
3898 d_musts = &d_add->musts;
3899 d_flags = &d_add->flags;
3900 d_min = &d_add->min;
3901 d_max = &d_add->max;
3902 break;
3903 case LYS_DEV_REPLACE:
3904 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003905 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003906 d = (struct lysp_deviate *)d_rpl;
3907 d_units = &d_rpl->units;
3908 d_flags = &d_rpl->flags;
3909 d_min = &d_rpl->min;
3910 d_max = &d_rpl->max;
3911 break;
3912 case LYS_DEV_DELETE:
3913 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003914 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003915 d = (struct lysp_deviate *)d_del;
3916 d_units = &d_del->units;
3917 d_uniques = &d_del->uniques;
3918 d_dflts = &d_del->dflts;
3919 d_musts = &d_del->musts;
3920 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003921 break;
3922 default:
3923 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003924 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003925 }
3926 d->mod = dev_mod;
3927
3928 /* insert into siblings */
3929 if (!*deviates) {
3930 *deviates = d;
3931 } else {
3932 for (iter = *deviates; iter->next; iter = iter->next);
3933 iter->next = d;
3934 }
3935
Radek Krejci6d6556c2018-11-08 09:37:45 +01003936 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003937 switch (kw) {
3938 case YANG_CONFIG:
3939 switch (dev_mod) {
3940 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003941 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003942 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003943 return LY_EVALID;
3944 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003945 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003946 break;
3947 }
3948 break;
3949 case YANG_DEFAULT:
3950 switch (dev_mod) {
3951 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02003952 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003953 return LY_EVALID;
3954 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003955 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003956 break;
3957 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003958 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003959 break;
3960 }
3961 break;
3962 case YANG_MANDATORY:
3963 switch (dev_mod) {
3964 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003965 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003966 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003967 return LY_EVALID;
3968 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003969 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003970 break;
3971 }
3972 break;
3973 case YANG_MAX_ELEMENTS:
3974 switch (dev_mod) {
3975 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003976 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003977 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003978 return LY_EVALID;
3979 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003980 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003981 break;
3982 }
3983 break;
3984 case YANG_MIN_ELEMENTS:
3985 switch (dev_mod) {
3986 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003987 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003988 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003989 return LY_EVALID;
3990 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003991 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003992 break;
3993 }
3994 break;
3995 case YANG_MUST:
3996 switch (dev_mod) {
3997 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003998 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02003999 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004000 return LY_EVALID;
4001 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004002 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004003 break;
4004 }
4005 break;
4006 case YANG_TYPE:
4007 switch (dev_mod) {
4008 case LYS_DEV_NOT_SUPPORTED:
4009 case LYS_DEV_ADD:
4010 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02004011 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004012 return LY_EVALID;
4013 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004014 if (d_rpl->type) {
David Sedlákb3077192019-06-19 10:55:37 +02004015 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004016 return LY_EVALID;
4017 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004018 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004019 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004020 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004021 break;
4022 }
4023 break;
4024 case YANG_UNIQUE:
4025 switch (dev_mod) {
4026 case LYS_DEV_NOT_SUPPORTED:
4027 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02004028 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004029 return LY_EVALID;
4030 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004031 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004032 break;
4033 }
4034 break;
4035 case YANG_UNITS:
4036 switch (dev_mod) {
4037 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02004038 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004039 return LY_EVALID;
4040 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004041 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004042 break;
4043 }
4044 break;
4045 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004046 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004047 break;
4048 default:
David Sedlákb3077192019-06-19 10:55:37 +02004049 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004050 return LY_EVALID;
4051 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004052 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004053 return ret;
4054}
4055
Michal Vaskoea5abea2018-09-18 13:10:54 +02004056/**
4057 * @brief Parse the deviation statement.
4058 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004059 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004060 * @param[in,out] data Data to read from, always moved to currently handled character.
4061 * @param[in,out] deviations Deviations to add to.
4062 *
4063 * @return LY_ERR values.
4064 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004065LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004066parse_deviation(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004067{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004068 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004069 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004070 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004071 enum yang_keyword kw;
4072 struct lysp_deviation *dev;
4073
Radek Krejci2c4e7172018-10-19 15:56:26 +02004074 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004075
4076 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004077 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Radek Krejcif09e4e82019-06-14 15:08:11 +02004078 YANG_CHECK_NONEMPTY(ctx, NULL, word_len, "deviation");
Radek Krejci44ceedc2018-10-02 15:54:31 +02004079 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004080
Radek Krejci6d6556c2018-11-08 09:37:45 +01004081 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004082 switch (kw) {
4083 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004084 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004085 break;
4086 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004087 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004088 break;
4089 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004090 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004091 break;
4092 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004093 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004094 break;
4095 default:
David Sedlákb3077192019-06-19 10:55:37 +02004096 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004097 return LY_EVALID;
4098 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004099 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004100 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004101checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004102 /* mandatory substatements */
4103 if (!dev->deviates) {
David Sedlákb3077192019-06-19 10:55:37 +02004104 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004105 return LY_EVALID;
4106 }
4107
4108 return ret;
4109}
4110
Michal Vaskoea5abea2018-09-18 13:10:54 +02004111/**
4112 * @brief Parse the feature statement.
4113 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004114 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004115 * @param[in,out] data Data to read from, always moved to currently handled character.
4116 * @param[in,out] features Features to add to.
4117 *
4118 * @return LY_ERR values.
4119 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004120LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004121parse_feature(struct lys_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004122{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004123 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004124 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004125 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004126 enum yang_keyword kw;
4127 struct lysp_feature *feat;
4128
Radek Krejci2c4e7172018-10-19 15:56:26 +02004129 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004130
4131 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004132 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004133 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004134
Radek Krejci6d6556c2018-11-08 09:37:45 +01004135 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004136 switch (kw) {
4137 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004138 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004139 break;
4140 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004141 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004142 break;
4143 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004144 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004145 break;
4146 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004147 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004148 break;
4149 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004150 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004151 break;
4152 default:
David Sedlákb3077192019-06-19 10:55:37 +02004153 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004154 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004155 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004156 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004157 return ret;
4158}
4159
Michal Vaskoea5abea2018-09-18 13:10:54 +02004160/**
4161 * @brief Parse the identity statement.
4162 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004163 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004164 * @param[in,out] data Data to read from, always moved to currently handled character.
4165 * @param[in,out] identities Identities to add to.
4166 *
4167 * @return LY_ERR values.
4168 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004169LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004170parse_identity(struct lys_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004171{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004172 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004173 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004174 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004175 enum yang_keyword kw;
4176 struct lysp_ident *ident;
4177
Radek Krejci2c4e7172018-10-19 15:56:26 +02004178 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179
4180 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004181 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004182 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004183
Radek Krejci6d6556c2018-11-08 09:37:45 +01004184 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004185 switch (kw) {
4186 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004187 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004188 break;
4189 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01004190 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004191 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004192 break;
4193 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004194 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004195 break;
4196 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004197 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004198 break;
4199 case YANG_BASE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004200 if (ident->bases && ctx->mod_version < 2) {
David Sedlákb3077192019-06-19 10:55:37 +02004201 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 +01004202 return LY_EVALID;
4203 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004204 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004205 break;
4206 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004207 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004208 break;
4209 default:
David Sedlákb3077192019-06-19 10:55:37 +02004210 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004211 return LY_EVALID;
4212 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004213 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004214 return ret;
4215}
4216
Michal Vaskoea5abea2018-09-18 13:10:54 +02004217/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004218 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004219 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004220 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004221 * @param[in,out] data Data to read from, always moved to currently handled character.
4222 * @param[in,out] mod Module to write to.
4223 *
4224 * @return LY_ERR values.
4225 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004226LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004227parse_module(struct lys_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004228{
4229 LY_ERR ret = 0;
4230 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004231 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004232 enum yang_keyword kw, prev_kw = 0;
4233 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004234 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004235
4236 /* (sub)module name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004237 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004238 INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004239
Radek Krejci6d6556c2018-11-08 09:37:45 +01004240 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004241
Radek Krejcie3846472018-10-15 15:24:51 +02004242#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004243 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 +02004244
Michal Vasko7fbc8162018-09-17 10:35:16 +02004245 switch (kw) {
4246 /* module header */
4247 case YANG_NAMESPACE:
4248 case YANG_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004249 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4250 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004251 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004252 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004253 break;
4254 /* linkage */
4255 case YANG_INCLUDE:
4256 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004257 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004258 break;
4259 /* meta */
4260 case YANG_ORGANIZATION:
4261 case YANG_CONTACT:
4262 case YANG_DESCRIPTION:
4263 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004264 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004265 break;
4266
4267 /* revision */
4268 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004269 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004270 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004271 /* body */
4272 case YANG_ANYDATA:
4273 case YANG_ANYXML:
4274 case YANG_AUGMENT:
4275 case YANG_CHOICE:
4276 case YANG_CONTAINER:
4277 case YANG_DEVIATION:
4278 case YANG_EXTENSION:
4279 case YANG_FEATURE:
4280 case YANG_GROUPING:
4281 case YANG_IDENTITY:
4282 case YANG_LEAF:
4283 case YANG_LEAF_LIST:
4284 case YANG_LIST:
4285 case YANG_NOTIFICATION:
4286 case YANG_RPC:
4287 case YANG_TYPEDEF:
4288 case YANG_USES:
4289 case YANG_CUSTOM:
4290 mod_stmt = Y_MOD_BODY;
4291 break;
4292 default:
4293 /* error handled in the next switch */
4294 break;
4295 }
Radek Krejcie3846472018-10-15 15:24:51 +02004296#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004297
Radek Krejcie3846472018-10-15 15:24:51 +02004298 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004299 switch (kw) {
4300 /* module header */
4301 case YANG_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004302 LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
4303 ctx->mod_version = mod->mod->version;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004304 break;
4305 case YANG_NAMESPACE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004306 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->mod->ns, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004307 break;
4308 case YANG_PREFIX:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004309 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->mod->prefix, Y_IDENTIF_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004310 break;
4311
4312 /* linkage */
4313 case YANG_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004314 LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004315 break;
4316 case YANG_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004317 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004318 break;
4319
4320 /* meta */
4321 case YANG_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004322 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->mod->org, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004323 break;
4324 case YANG_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004325 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->mod->contact, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004326 break;
4327 case YANG_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004328 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->mod->dsc, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004329 break;
4330 case YANG_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004331 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->mod->ref, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004332 break;
4333
4334 /* revision */
4335 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004336 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004337 break;
4338
4339 /* body */
4340 case YANG_ANYDATA:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004341 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci10113652018-11-14 16:56:50 +01004342 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004343 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004344 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004345 break;
4346 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004347 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004348 break;
4349 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004350 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004351 break;
4352 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004353 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004354 break;
4355 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004356 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004357 break;
4358 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004359 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004360 break;
4361 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004362 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004363 break;
4364
4365 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004366 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004367 break;
4368 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004369 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004370 break;
4371 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004372 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004373 break;
4374 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004375 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004376 break;
4377 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004378 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004379 break;
4380 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004381 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004382 break;
4383 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004384 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004385 break;
4386 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004387 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004388 break;
4389 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004390 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004391 break;
4392 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004393 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004394 break;
4395
4396 default:
David Sedlákb3077192019-06-19 10:55:37 +02004397 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004398 return LY_EVALID;
4399 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004400 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004401 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004402
Radek Krejci6d6556c2018-11-08 09:37:45 +01004403checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004404 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02004405 LY_CHECK_RET(parse_finalize_reallocated(ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004406
Michal Vasko7fbc8162018-09-17 10:35:16 +02004407 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004408 if (!mod->mod->ns) {
David Sedlákb3077192019-06-19 10:55:37 +02004409 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004410 return LY_EVALID;
4411 } else if (!mod->mod->prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02004412 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004413 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004414 }
4415
Radek Krejcie9e987e2018-10-31 12:50:27 +01004416 /* submodules share the namespace with the module names, so there must not be
4417 * a submodule of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004418 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->mod->name, NULL);
4419 if (dup) {
David Sedlákb3077192019-06-19 10:55:37 +02004420 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 +01004421 return LY_EVALID;
4422 }
4423
4424 return ret;
4425}
4426
4427/**
4428 * @brief Parse submodule substatements.
4429 *
4430 * @param[in] ctx yang parser context for logging.
4431 * @param[in,out] data Data to read from, always moved to currently handled character.
4432 * @param[out] submod Parsed submodule structure.
4433 *
4434 * @return LY_ERR values.
4435 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004436LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004437parse_submodule(struct lys_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004438{
4439 LY_ERR ret = 0;
4440 char *buf, *word;
4441 size_t word_len;
4442 enum yang_keyword kw, prev_kw = 0;
4443 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4444 struct lysp_submodule *dup;
4445
4446 /* submodule name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004447 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004448 INSERT_WORD(ctx, buf, submod->name, word, word_len);
4449
4450 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
4451
4452#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004453 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 +01004454
4455 switch (kw) {
4456 /* module header */
4457 case YANG_BELONGS_TO:
4458 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4459 break;
4460 case YANG_YANG_VERSION:
4461 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4462 break;
4463 /* linkage */
4464 case YANG_INCLUDE:
4465 case YANG_IMPORT:
4466 CHECK_ORDER(Y_MOD_LINKAGE);
4467 break;
4468 /* meta */
4469 case YANG_ORGANIZATION:
4470 case YANG_CONTACT:
4471 case YANG_DESCRIPTION:
4472 case YANG_REFERENCE:
4473 CHECK_ORDER(Y_MOD_META);
4474 break;
4475
4476 /* revision */
4477 case YANG_REVISION:
4478 CHECK_ORDER(Y_MOD_REVISION);
4479 break;
4480 /* body */
4481 case YANG_ANYDATA:
4482 case YANG_ANYXML:
4483 case YANG_AUGMENT:
4484 case YANG_CHOICE:
4485 case YANG_CONTAINER:
4486 case YANG_DEVIATION:
4487 case YANG_EXTENSION:
4488 case YANG_FEATURE:
4489 case YANG_GROUPING:
4490 case YANG_IDENTITY:
4491 case YANG_LEAF:
4492 case YANG_LEAF_LIST:
4493 case YANG_LIST:
4494 case YANG_NOTIFICATION:
4495 case YANG_RPC:
4496 case YANG_TYPEDEF:
4497 case YANG_USES:
4498 case YANG_CUSTOM:
4499 mod_stmt = Y_MOD_BODY;
4500 break;
4501 default:
4502 /* error handled in the next switch */
4503 break;
4504 }
4505#undef CHECK_ORDER
4506
4507 prev_kw = kw;
4508 switch (kw) {
4509 /* module header */
4510 case YANG_YANG_VERSION:
4511 LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
4512 ctx->mod_version = submod->version;
4513 break;
4514 case YANG_BELONGS_TO:
4515 LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
4516 break;
4517
4518 /* linkage */
4519 case YANG_INCLUDE:
4520 LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
4521 break;
4522 case YANG_IMPORT:
4523 LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
4524 break;
4525
4526 /* meta */
4527 case YANG_ORGANIZATION:
4528 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
4529 break;
4530 case YANG_CONTACT:
4531 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
4532 break;
4533 case YANG_DESCRIPTION:
4534 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
4535 break;
4536 case YANG_REFERENCE:
4537 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
4538 break;
4539
4540 /* revision */
4541 case YANG_REVISION:
4542 LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
4543 break;
4544
4545 /* body */
4546 case YANG_ANYDATA:
4547 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
4548 /* fall through */
4549 case YANG_ANYXML:
4550 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
4551 break;
4552 case YANG_CHOICE:
4553 LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
4554 break;
4555 case YANG_CONTAINER:
4556 LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
4557 break;
4558 case YANG_LEAF:
4559 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
4560 break;
4561 case YANG_LEAF_LIST:
4562 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
4563 break;
4564 case YANG_LIST:
4565 LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
4566 break;
4567 case YANG_USES:
4568 LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
4569 break;
4570
4571 case YANG_AUGMENT:
4572 LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
4573 break;
4574 case YANG_DEVIATION:
4575 LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
4576 break;
4577 case YANG_EXTENSION:
4578 LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
4579 break;
4580 case YANG_FEATURE:
4581 LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
4582 break;
4583 case YANG_GROUPING:
4584 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
4585 break;
4586 case YANG_IDENTITY:
4587 LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
4588 break;
4589 case YANG_NOTIFICATION:
4590 LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
4591 break;
4592 case YANG_RPC:
4593 LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
4594 break;
4595 case YANG_TYPEDEF:
4596 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
4597 break;
4598 case YANG_CUSTOM:
4599 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
4600 break;
4601
4602 default:
David Sedlákb3077192019-06-19 10:55:37 +02004603 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004604 return LY_EVALID;
4605 }
4606 }
4607 LY_CHECK_RET(ret);
4608
4609checks:
4610 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02004611 LY_CHECK_RET(parse_finalize_reallocated(ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004612
4613 /* mandatory substatements */
4614 if (!submod->belongsto) {
David Sedlákb3077192019-06-19 10:55:37 +02004615 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004616 return LY_EVALID;
4617 }
4618
4619 /* submodules share the namespace with the module names, so there must not be
4620 * a submodule of the same name in the context, no need for revision matching */
4621 dup = ly_ctx_get_submodule(ctx->ctx, NULL, submod->name, NULL);
4622 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
David Sedlákb3077192019-06-19 10:55:37 +02004623 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004624 return LY_EVALID;
4625 }
4626
Michal Vasko7fbc8162018-09-17 10:35:16 +02004627 return ret;
4628}
4629
Radek Krejcid4557c62018-09-17 11:42:09 +02004630LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004631yang_parse_submodule(struct lys_parser_ctx *context, const char *data, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004632{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004633 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004634 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004635 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004636 enum yang_keyword kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004637 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004638
4639 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004640 ret = get_keyword(context, &data, &kw, &word, &word_len);
4641 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004642
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004643 if (kw == YANG_MODULE) {
4644 LOGERR(context->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
4645 ret = LY_EINVAL;
4646 goto cleanup;
4647 } else if (kw != YANG_SUBMODULE) {
David Sedlákb3077192019-06-19 10:55:37 +02004648 LOGVAL_PARSER(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004649 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004650 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004651 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004652 }
4653
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004654 mod_p = calloc(1, sizeof *mod_p);
4655 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4656 mod_p->parsing = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004657
4658 /* substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004659 ret = parse_submodule(context, &data, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004660 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004661
4662 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004663 while(*data && isspace(*data)) {
4664 data++;
4665 }
4666 if (*data) {
David Sedlákb3077192019-06-19 10:55:37 +02004667 LOGVAL_PARSER(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004668 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004669 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004670 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004671 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004672
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004673 mod_p->parsing = 0;
4674 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004675
Radek Krejcibbe09a92018-11-08 09:36:54 +01004676cleanup:
4677 if (ret) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004678 lysp_submodule_free(context->ctx, mod_p);
4679 }
4680
4681 return ret;
4682}
4683
4684LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004685yang_parse_module(struct lys_parser_ctx *context, const char *data, struct lys_module *mod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004686{
4687 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004688 char *word;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004689 size_t word_len;
4690 enum yang_keyword kw;
4691 struct lysp_module *mod_p = NULL;
4692
4693 /* "module"/"submodule" */
4694 ret = get_keyword(context, &data, &kw, &word, &word_len);
4695 LY_CHECK_GOTO(ret, cleanup);
4696
4697 if (kw == YANG_SUBMODULE) {
4698 LOGERR(context->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
4699 ret = LY_EINVAL;
4700 goto cleanup;
4701 } else if (kw != YANG_MODULE) {
David Sedlákb3077192019-06-19 10:55:37 +02004702 LOGVAL_PARSER(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004703 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004704 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004705 goto cleanup;
4706 }
4707
4708 mod_p = calloc(1, sizeof *mod_p);
4709 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4710 mod_p->mod = mod;
4711 mod_p->parsing = 1;
4712
4713 /* substatements */
4714 ret = parse_module(context, &data, mod_p);
4715 LY_CHECK_GOTO(ret, cleanup);
4716
4717 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004718 while(*data && isspace(*data)) {
4719 data++;
4720 }
4721 if (*data) {
David Sedlákb3077192019-06-19 10:55:37 +02004722 LOGVAL_PARSER(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004723 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004724 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004725 goto cleanup;
4726 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004727
4728 mod_p->parsing = 0;
4729 mod->parsed = mod_p;
4730
4731cleanup:
4732 if (ret) {
4733 lysp_module_free(mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004734 }
4735
Michal Vasko7fbc8162018-09-17 10:35:16 +02004736 return ret;
4737}