blob: 6452b10add4994a0cbb852c4e6731c0a6d8c705c [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/**
Radek Krejciceaf2122019-01-02 15:03:26 +010035 * @brief Insert WORD into the libyang context's dictionary and store as TARGET.
36 * @param[in] CTX yang parser context to access libyang context.
37 * @param[in] BUF buffer in case the word is not a constant and can be inserted directly (zero-copy)
38 * @param[out] TARGET variable where to store the pointer to the inserted value.
39 * @param[in] WORD string to store.
40 * @param[in] LEN length of the string in WORD to store.
41 */
Radek Krejci9fcacc12018-10-11 15:59:11 +020042#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
43 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
Radek Krejcif09e4e82019-06-14 15:08:11 +020044 else {(TARGET) = lydict_insert((CTX)->ctx, LEN ? WORD : "", LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020045
Radek Krejciceaf2122019-01-02 15:03:26 +010046/**
47 * @brief Move the DATA pointer by COUNT items. Also updates the indent value in yang parser context
48 * @param[in] CTX yang parser context to update its indent value.
49 * @param[in,out] DATA pointer to move
50 * @param[in] COUNT number of items for which the DATA pointer is supposed to move on.
51 */
Radek Krejci2b610482019-01-02 13:36:09 +010052#define MOVE_INPUT(CTX, DATA, COUNT) (*(DATA))+=COUNT;(CTX)->indent+=COUNT
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020053
Michal Vaskoea5abea2018-09-18 13:10:54 +020054/**
55 * @brief Loop through all substatements providing, return if there are none.
56 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020057 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020058 * @param[in] DATA Raw data to read from.
59 * @param[out] KW YANG keyword read.
60 * @param[out] WORD Pointer to the keyword itself.
61 * @param[out] WORD_LEN Length of the keyword.
62 * @param[out] ERR Variable for error storing.
63 *
64 * @return In case there are no substatements or a fatal error encountered.
65 */
Radek Krejci6d6556c2018-11-08 09:37:45 +010066#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010067 LY_CHECK_RET(get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020068 if (KW == YANG_SEMICOLON) { \
Radek Krejci6d6556c2018-11-08 09:37:45 +010069 CHECKGOTO; \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010070 return LY_SUCCESS; \
Michal Vasko7fbc8162018-09-17 10:35:16 +020071 } \
72 if (KW != YANG_LEFT_BRACE) { \
David Sedlákb3077192019-06-19 10:55:37 +020073 LOGVAL_PARSER(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020074 return LY_EVALID; \
75 } \
76 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
77 !ERR && (KW != YANG_RIGHT_BRACE); \
78 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
79
Radek Krejciceaf2122019-01-02 15:03:26 +010080/**
81 * @brief Check module version is at least 2 (YANG 1.1) because of the keyword presence.
82 * Logs error message and returns LY_EVALID in case of module in YANG version 1.0.
83 * @param[in] CTX yang parser context to get current module and for logging.
84 * @param[in] KW keyword allowed only in YANG version 1.1 (or later) - for logging.
85 * @param[in] PARENT parent statement where the KW is present - for logging.
86 */
87#define YANG_CHECK_STMTVER2_RET(CTX, KW, PARENT) \
David Sedlákb3077192019-06-19 10:55:37 +020088 if ((CTX)->mod_version < 2) {LOGVAL_PARSER((CTX), LY_VCODE_INCHILDSTMT2, KW, PARENT); return LY_EVALID;}
Radek Krejci10113652018-11-14 16:56:50 +010089
Radek Krejci2d7a47b2019-05-16 13:34:10 +020090LY_ERR parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
91LY_ERR parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
92LY_ERR parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
93LY_ERR parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
94LY_ERR parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
95LY_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 +020096
Radek Krejci7fc68292019-06-12 13:51:09 +020097static LY_ERR parse_finalize_reallocated(struct lys_parser_ctx *ctx, struct lysp_grp *groupings, struct lysp_augment *augments,
98 struct lysp_action *actions, struct lysp_notif *notifs);
99
Michal Vaskoea5abea2018-09-18 13:10:54 +0200100/**
101 * @brief Add another character to dynamic buffer, a low-level function.
102 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200103 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200104 *
Radek Krejci404251e2018-10-09 12:06:44 +0200105 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200106 * @param[in, out] input Input string to process.
107 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200108 * @param[in,out] buf Buffer to use, can be moved by realloc().
109 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200110 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200111 *
112 * @return LY_ERR values.
113 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200114LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200115buf_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 +0200116{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200117 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200118 *buf_len += 16;
119 *buf = ly_realloc(*buf, *buf_len);
120 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
121 }
Radek Krejcic0917392019-04-10 13:04:04 +0200122 if (*buf_used) {
123 memcpy(&(*buf)[*buf_used], *input, len);
124 } else {
125 memcpy(*buf, *input, len);
126 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200127
Radek Krejci44ceedc2018-10-02 15:54:31 +0200128 (*buf_used) += len;
129 (*input) += len;
130
Michal Vasko7fbc8162018-09-17 10:35:16 +0200131 return LY_SUCCESS;
132}
133
Michal Vaskoea5abea2018-09-18 13:10:54 +0200134/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200135 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
136 *
137 * @param[in] ctx yang parser context for logging.
138 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
139 * when function returns.
140 * @param[in] arg Type of the input string to select method of checking character validity.
141 * @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 +0200142 * 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 +0200143 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
144 * @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 +0200145 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200146 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
David Sedlák40bb13b2019-07-10 14:34:18 +0200147 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
148 * 0 - colon not yet found (no prefix)
149 * 1 - \p c is the colon character
150 * 2 - prefix already processed, now processing the identifier
Michal Vaskoea5abea2018-09-18 13:10:54 +0200151 *
152 * @return LY_ERR values.
153 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200154LY_ERR
David Sedlák40bb13b2019-07-10 14:34:18 +0200155buf_store_char(struct lys_parser_ctx *ctx, const char **input, enum yang_arg arg, char **word_p,
156 size_t *word_len, char **word_b, size_t *buf_len, int need_buf, int *prefix)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200157{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200158 unsigned int c;
159 size_t len;
160
Radek Krejcif29b7c32019-04-09 16:17:49 +0200161 /* check valid combination of input paremeters - if need_buf specified, word_b must be provided */
162 assert(!need_buf || (need_buf && word_b));
163
Radek Krejci44ceedc2018-10-02 15:54:31 +0200164 /* get UTF8 code point (and number of bytes coding the character) */
165 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
David Sedlákb3077192019-06-19 10:55:37 +0200166 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200167 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200168 if (c == '\n') {
169 ctx->indent = 0;
170 } else {
171 /* note - even the multibyte character is count as 1 */
172 ++ctx->indent;
173 }
174
Radek Krejci44ceedc2018-10-02 15:54:31 +0200175 /* check character validity */
176 switch (arg) {
177 case Y_IDENTIF_ARG:
David Sedlák4a650532019-07-10 11:55:18 +0200178 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, !(*word_len), NULL));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200179 break;
180 case Y_PREF_IDENTIF_ARG:
David Sedlák40bb13b2019-07-10 14:34:18 +0200181 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, !(*word_len), prefix));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200182 break;
183 case Y_STR_ARG:
184 case Y_MAYBE_STR_ARG:
David Sedlák4a650532019-07-10 11:55:18 +0200185 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200186 break;
187 }
188
Michal Vasko7fbc8162018-09-17 10:35:16 +0200189 if (word_b && *word_b) {
190 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200191 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200192 return LY_EMEM;
193 }
194
195 /* in case of realloc */
196 *word_p = *word_b;
Radek Krejcif29b7c32019-04-09 16:17:49 +0200197 } else if (word_b && need_buf) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200198 /* first time we need a buffer, copy everything read up to now */
199 if (*word_len) {
200 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200201 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200202 *buf_len = *word_len;
203 memcpy(*word_b, *word_p, *word_len);
204 }
205
206 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200207 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200208 return LY_EMEM;
209 }
210
211 /* in case of realloc */
212 *word_p = *word_b;
213 } else {
214 /* just remember the first character pointer */
215 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200216 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200217 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200218 /* ... and update the word's length */
219 (*word_len) += len;
220 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200221 }
222
223 return LY_SUCCESS;
224}
225
Michal Vaskoea5abea2018-09-18 13:10:54 +0200226/**
227 * @brief Skip YANG comment in data.
228 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200229 * @param[in] ctx yang parser context for logging.
230 * @param[in,out] data Data to read from, automatically moved after the comment.
231 * @param[in] comment Type of the comment to process:
232 * 1 for a one-line comment,
233 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200234 *
235 * @return LY_ERR values.
236 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200237LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200238skip_comment(struct lys_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200239{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200240 /* internal statuses: 0 - comment ended,
241 * 1 - in line comment,
242 * 2 - in block comment,
243 * 3 - in block comment with last read character '*'
244 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200245 while (**data && comment) {
246 switch (comment) {
247 case 1:
248 if (**data == '\n') {
249 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200250 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200251 }
252 break;
253 case 2:
254 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200255 comment = 3;
256 } else if (**data == '\n') {
257 ++ctx->line;
258 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200259 break;
260 case 3:
261 if (**data == '/') {
262 comment = 0;
Radek Krejci5b930492019-06-11 14:54:08 +0200263 } else if (**data != '*') {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200264 if (**data == '\n') {
265 ++ctx->line;
266 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200267 comment = 2;
268 }
269 break;
270 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200271 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200272 }
273
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200274 if (**data == '\n') {
275 ctx->indent = 0;
276 } else {
277 ++ctx->indent;
278 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200279 ++(*data);
280 }
281
282 if (!**data && (comment > 1)) {
David Sedlákb3077192019-06-19 10:55:37 +0200283 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Unexpected end-of-input, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200284 return LY_EVALID;
285 }
286
287 return LY_SUCCESS;
288}
289
Michal Vaskoea5abea2018-09-18 13:10:54 +0200290/**
291 * @brief Read a quoted string from data.
292 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200293 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200294 * @param[in,out] data Data to read from, always moved to currently handled character.
295 * @param[in] arg Type of YANG keyword argument expected.
296 * @param[out] word_p Pointer to the read quoted string.
297 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
298 * set to NULL. Otherwise equal to \p word_p.
299 * @param[out] word_len Length of the read quoted string.
300 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
301 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
302 * indenation in the final quoted string.
303 *
304 * @return LY_ERR values.
305 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200306static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200307read_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 +0200308 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200309{
310 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
311 * 4 - string finished, now skipping whitespaces looking for +,
312 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200313 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200314 const char *c;
David Sedlák40bb13b2019-07-10 14:34:18 +0200315 int prefix = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200316
317 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200318 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200319 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200320 } else {
321 assert(**data == '\'');
322 string = 1;
323 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200324 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200325
326 while (**data && string) {
327 switch (string) {
328 case 1:
329 switch (**data) {
330 case '\'':
331 /* string may be finished, but check for + */
332 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200333 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200334 break;
335 default:
336 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200337 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 +0200338 break;
339 }
340 break;
341 case 2:
342 switch (**data) {
343 case '\"':
344 /* string may be finished, but check for + */
345 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200346 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200347 break;
348 case '\\':
349 /* special character following */
350 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200351 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200352 break;
353 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200354 if (current_indent < block_indent) {
355 ++current_indent;
356 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200357 } else {
358 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200359 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 +0200360 }
361 break;
362 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200363 if (current_indent < block_indent) {
364 assert(need_buf);
365 current_indent += 8;
366 ctx->indent += 8;
367 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
368 /* store leftover spaces from the tab */
369 c = " ";
David Sedlák40bb13b2019-07-10 14:34:18 +0200370 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 +0200371 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200372 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200373 } else {
374 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200375 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 +0200376 /* additional characters for indentation - only 1 was count in buf_store_char */
377 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200378 }
379 break;
380 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200381 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200382 /* we will be removing the indents so we need our own buffer */
383 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200384
385 /* remove trailing tabs and spaces */
386 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
387 --(*word_len);
388 }
389
390 /* start indentation */
391 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200392 }
393
394 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200395 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 +0200396
397 /* maintain line number */
398 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200399
400 /* reset context indentation counter for possible string after this one */
401 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200402 break;
403 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200404 /* first non-whitespace character, stop eating indentation */
405 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200406
407 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200408 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 +0200409 break;
410 }
411 break;
412 case 3:
413 /* string encoded characters */
414 switch (**data) {
415 case 'n':
416 c = "\n";
417 break;
418 case 't':
419 c = "\t";
420 break;
421 case '\"':
422 c = *data;
423 break;
424 case '\\':
425 c = *data;
426 break;
427 default:
David Sedlákb3077192019-06-19 10:55:37 +0200428 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200429 return LY_EVALID;
430 }
431
432 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200433 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 +0200434
435 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200436 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200437 break;
438 case 4:
439 switch (**data) {
440 case '+':
441 /* string continues */
442 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200443 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200444 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200445 case '\n':
446 ++ctx->line;
447 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200448 case ' ':
449 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200450 /* just skip */
451 break;
452 default:
453 /* string is finished */
454 goto string_end;
455 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200456 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200457 break;
458 case 5:
459 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200460 case '\n':
461 ++ctx->line;
462 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200463 case ' ':
464 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200465 /* skip */
466 break;
467 case '\'':
468 string = 1;
469 break;
470 case '\"':
471 string = 2;
472 break;
473 default:
474 /* it must be quoted again */
David Sedlákb3077192019-06-19 10:55:37 +0200475 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200476 return LY_EVALID;
477 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200478 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200479 break;
480 default:
481 return LY_EINT;
482 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200483 }
484
485string_end:
Radek Krejci4e199f52019-05-28 09:09:28 +0200486 if (arg <= Y_PREF_IDENTIF_ARG && !(*word_len)) {
487 /* empty identifier */
David Sedlákb3077192019-06-19 10:55:37 +0200488 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Statement argument is required.");
Radek Krejci4e199f52019-05-28 09:09:28 +0200489 return LY_EVALID;
490 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200491 return LY_SUCCESS;
492}
493
Michal Vaskoea5abea2018-09-18 13:10:54 +0200494/**
495 * @brief Get another YANG string from the raw data.
496 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200497 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200498 * @param[in,out] data Data to read from, always moved to currently handled character.
499 * @param[in] arg Type of YANG keyword argument expected.
Radek Krejcid3ca0632019-04-16 16:54:54 +0200500 * @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 +0200501 * @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 +0200502 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
503 * set to NULL. Otherwise equal to \p word_p.
504 * @param[out] word_len Length of the read string.
505 *
506 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200507 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200508LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200509get_argument(struct lys_parser_ctx *ctx, const char **data, enum yang_arg arg,
Radek Krejcid3ca0632019-04-16 16:54:54 +0200510 uint16_t *flags, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200511{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200512 size_t buf_len = 0;
David Sedlák40bb13b2019-07-10 14:34:18 +0200513 int prefix = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200514 /* word buffer - dynamically allocated */
515 *word_b = NULL;
516
517 /* word pointer - just a pointer to data */
518 *word_p = NULL;
519
520 *word_len = 0;
521 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200522 switch (**data) {
523 case '\'':
524 case '\"':
525 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200526 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
David Sedlákb3077192019-06-19 10:55:37 +0200527 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data,
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200528 "unquoted string character, optsep, semicolon or opening brace");
529 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200530 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200531 if (flags) {
532 (*flags) |= (**data) == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
533 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100534 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200535 goto str_end;
536 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200537 if ((*data)[1] == '/') {
538 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200539 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100540 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200541 } else if ((*data)[1] == '*') {
542 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200543 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100544 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200545 } else {
546 /* not a comment after all */
David Sedlák40bb13b2019-07-10 14:34:18 +0200547 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 +0200548 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200549 break;
550 case ' ':
551 if (*word_len) {
552 /* word is finished */
553 goto str_end;
554 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200555 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200556 break;
557 case '\t':
558 if (*word_len) {
559 /* word is finished */
560 goto str_end;
561 }
562 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200563 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200564
565 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200566 break;
567 case '\n':
568 if (*word_len) {
569 /* word is finished */
570 goto str_end;
571 }
572 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200573 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200574
575 /* track line numbers */
576 ++ctx->line;
577
578 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200579 break;
580 case ';':
581 case '{':
582 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
583 /* word is finished */
584 goto str_end;
585 }
586
David Sedlákb3077192019-06-19 10:55:37 +0200587 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200588 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200589 case '}':
590 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
David Sedlákb3077192019-06-19 10:55:37 +0200591 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data,
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200592 "unquoted string character, optsep, semicolon or opening brace");
593 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200594 default:
David Sedlák40bb13b2019-07-10 14:34:18 +0200595 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 +0200596 break;
597 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200598 }
599
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200600 /* unexpected end of loop */
David Sedlákb3077192019-06-19 10:55:37 +0200601 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200602 return LY_EVALID;
603
Michal Vasko7fbc8162018-09-17 10:35:16 +0200604str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200605 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200606 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200607 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
608 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
609 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200610 *word_p = *word_b;
611 }
612
613 return LY_SUCCESS;
614}
615
Michal Vaskoea5abea2018-09-18 13:10:54 +0200616/**
617 * @brief Get another YANG keyword from the raw data.
618 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200619 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200620 * @param[in,out] data Data to read from, always moved to currently handled character.
621 * @param[out] kw YANG keyword read.
622 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
623 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
624 *
625 * @return LY_ERR values.
626 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200627LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200628get_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 +0200629{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200630 int prefix;
631 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200632 unsigned int c;
633 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200634
635 if (word_p) {
636 *word_p = NULL;
637 *word_len = 0;
638 }
639
640 /* first skip "optsep", comments */
641 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200642 switch (**data) {
643 case '/':
644 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200645 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200646 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100647 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200648 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200649 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200650 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100651 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200652 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200653 /* error - not a comment after all, keyword cannot start with slash */
David Sedlákb3077192019-06-19 10:55:37 +0200654 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
Radek Krejcidcc7b322018-10-11 14:24:02 +0200655 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200656 }
Radek Krejci13028282019-06-11 14:56:48 +0200657 continue;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200658 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200659 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200660 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200661 ctx->indent = 0;
662 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200663 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200664 /* skip whitespaces (optsep) */
665 ++ctx->indent;
666 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200667 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200668 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200669 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200670 break;
671 default:
672 /* either a keyword start or an invalid character */
673 goto keyword_start;
674 }
675
676 ++(*data);
677 }
678
679keyword_start:
680 word_start = *data;
David Sedlák5f8f0332019-06-18 16:34:30 +0200681 *kw = lysp_match_kw(ctx, data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200682
David Sedlák1bccdfa2019-06-17 15:55:27 +0200683 if (*kw == YANG_SEMICOLON || *kw == YANG_LEFT_BRACE || *kw == YANG_RIGHT_BRACE) {
Radek Krejci626df482018-10-11 15:06:31 +0200684 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200685 }
686
687 if (*kw != YANG_NONE) {
688 /* make sure we have the whole keyword */
689 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200690 case '\n':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200691 case '\t':
Radek Krejciabdd8062019-06-11 16:44:19 +0200692 case ' ':
693 /* mandatory "sep" is just checked, not eaten so nothing in the context is updated */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200694 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200695 case ':':
696 /* keyword is not actually a keyword, but prefix of an extension.
697 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
698 * and we will be checking the keyword (extension instance) itself */
699 prefix = 1;
700 MOVE_INPUT(ctx, data, 1);
701 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200702 case '{':
703 /* allowed only for input and output statements which can be without arguments */
704 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
705 break;
706 }
707 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200708 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200709 MOVE_INPUT(ctx, data, 1);
David Sedlákb3077192019-06-19 10:55:37 +0200710 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
Radek Krejci44ceedc2018-10-02 15:54:31 +0200711 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200712 return LY_EVALID;
713 }
714 } else {
715 /* still can be an extension */
716 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200717extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200718 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200719 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
David Sedlákb3077192019-06-19 10:55:37 +0200720 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200721 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200722 /* check character validity */
David Sedlák4a650532019-07-10 11:55:18 +0200723 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200724 }
725 if (!**data) {
David Sedlákb3077192019-06-19 10:55:37 +0200726 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200727 return LY_EVALID;
728 }
729
730 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200731 if (prefix != 2) {
David Sedlákb3077192019-06-19 10:55:37 +0200732 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200733 return LY_EVALID;
734 }
735
736 *kw = YANG_CUSTOM;
737 }
Radek Krejci626df482018-10-11 15:06:31 +0200738success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200739 if (word_p) {
740 *word_p = (char *)word_start;
741 *word_len = *data - word_start;
742 }
743
744 return LY_SUCCESS;
745}
746
Michal Vaskoea5abea2018-09-18 13:10:54 +0200747/**
748 * @brief Parse extension instance substatements.
749 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200750 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200751 * @param[in,out] data Data to read from, always moved to currently handled character.
752 * @param[in] word Extension instance substatement name (keyword).
753 * @param[in] word_len Extension instance substatement name length.
754 * @param[in,out] child Children of this extension instance to add to.
755 *
756 * @return LY_ERR values.
757 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200758static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200759parse_ext_substmt(struct lys_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200760 struct lysp_stmt **child)
761{
762 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100763 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200764 enum yang_keyword kw;
765 struct lysp_stmt *stmt, *par_child;
766
767 stmt = calloc(1, sizeof *stmt);
768 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
769
Radek Krejcibb9b1982019-04-08 14:24:59 +0200770 /* insert into parent statements */
771 if (!*child) {
772 *child = stmt;
773 } else {
774 for (par_child = *child; par_child->next; par_child = par_child->next);
775 par_child->next = stmt;
776 }
777
Radek Krejci44ceedc2018-10-02 15:54:31 +0200778 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200779
780 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200781 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200782
Radek Krejci0ae092d2018-09-20 16:43:19 +0200783 if (word) {
784 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200785 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200786 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200787 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200788 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200789 }
790
Radek Krejci6d6556c2018-11-08 09:37:45 +0100791 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100792 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200793 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200794 return ret;
795}
796
Michal Vaskoea5abea2018-09-18 13:10:54 +0200797/**
798 * @brief Parse extension instance.
799 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200800 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200801 * @param[in,out] data Data to read from, always moved to currently handled character.
802 * @param[in] ext_name Extension instance substatement name (keyword).
803 * @param[in] ext_name_len Extension instance substatement name length.
804 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
805 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
806 * @param[in,out] exts Extension instances to add to.
807 *
808 * @return LY_ERR values.
809 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200810static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200811parse_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 +0200812 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
813{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100814 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200815 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200816 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200817 struct lysp_ext_instance *e;
818 enum yang_keyword kw;
819
Radek Krejci2c4e7172018-10-19 15:56:26 +0200820 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200821
822 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200823 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200824 e->insubstmt = insubstmt;
825 e->insubstmt_index = insubstmt_index;
826
827 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200828 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200829
Radek Krejci0ae092d2018-09-20 16:43:19 +0200830 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200831 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200832 }
833
Radek Krejci6d6556c2018-11-08 09:37:45 +0100834 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100835 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200836 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200837 return ret;
838}
839
Michal Vaskoea5abea2018-09-18 13:10:54 +0200840/**
841 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
842 * description, etc...
843 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200844 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200845 * @param[in,out] data Data to read from, always moved to currently handled character.
846 * @param[in] substmt Type of this substatement.
847 * @param[in] substmt_index Index of this substatement.
848 * @param[in,out] value Place to store the parsed value.
849 * @param[in] arg Type of the YANG keyword argument (of the value).
850 * @param[in,out] exts Extension instances to add to.
851 *
852 * @return LY_ERR values.
853 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200854static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200855parse_text_field(struct lys_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200856 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
857{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100858 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200859 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200860 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200861 enum yang_keyword kw;
862
863 if (*value) {
David Sedlákb3077192019-06-19 10:55:37 +0200864 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200865 return LY_EVALID;
866 }
867
868 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200869 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200870
871 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200872 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200873
Radek Krejci6d6556c2018-11-08 09:37:45 +0100874 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200875 switch (kw) {
876 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100877 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200878 break;
879 default:
David Sedlákb3077192019-06-19 10:55:37 +0200880 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200881 return LY_EVALID;
882 }
883 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200884 return ret;
885}
886
Michal Vaskoea5abea2018-09-18 13:10:54 +0200887/**
888 * @brief Parse the yang-version statement.
889 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200890 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200891 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100892 * @param[out] version Storage for the parsed information.
893 * @param[in, out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200894 *
895 * @return LY_ERR values.
896 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200897static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200898parse_yangversion(struct lys_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200899{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100900 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200901 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200902 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200903 enum yang_keyword kw;
904
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100905 if (*version) {
David Sedlákb3077192019-06-19 10:55:37 +0200906 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200907 return LY_EVALID;
908 }
909
910 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200911 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200912
913 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100914 *version = LYS_VERSION_1_0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200915 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100916 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200917 } else {
David Sedlákb3077192019-06-19 10:55:37 +0200918 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200919 free(buf);
920 return LY_EVALID;
921 }
922 free(buf);
923
Radek Krejci6d6556c2018-11-08 09:37:45 +0100924 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200925 switch (kw) {
926 case YANG_CUSTOM:
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100927 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200928 break;
929 default:
David Sedlákb3077192019-06-19 10:55:37 +0200930 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200931 return LY_EVALID;
932 }
933 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200934 return ret;
935}
936
Michal Vaskoea5abea2018-09-18 13:10:54 +0200937/**
938 * @brief Parse the belongs-to statement.
939 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200940 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200941 * @param[in,out] data Data to read from, always moved to currently handled character.
942 * @param[in,out] belongsto Place to store the parsed value.
943 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
944 * @param[in,out] exts Extension instances to add to.
945 *
946 * @return LY_ERR values.
947 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200948static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200949parse_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 +0200950{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100951 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200952 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200953 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200954 enum yang_keyword kw;
955
956 if (*belongsto) {
David Sedlákb3077192019-06-19 10:55:37 +0200957 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200958 return LY_EVALID;
959 }
960
961 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200962 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200963
Radek Krejci44ceedc2018-10-02 15:54:31 +0200964 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejcif09e4e82019-06-14 15:08:11 +0200965
Radek Krejci6d6556c2018-11-08 09:37:45 +0100966 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200967 switch (kw) {
968 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100969 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200970 break;
971 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100972 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200973 break;
974 default:
David Sedlákb3077192019-06-19 10:55:37 +0200975 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200976 return LY_EVALID;
977 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200978 }
Radek Krejcic59bc972018-09-17 16:13:06 +0200979 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +0100980checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200981 /* mandatory substatements */
982 if (!*prefix) {
David Sedlákb3077192019-06-19 10:55:37 +0200983 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200984 return LY_EVALID;
985 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200986 return ret;
987}
988
Michal Vaskoea5abea2018-09-18 13:10:54 +0200989/**
990 * @brief Parse the revision-date statement.
991 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200992 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200993 * @param[in,out] data Data to read from, always moved to currently handled character.
994 * @param[in,out] rev Array to store the parsed value in.
995 * @param[in,out] exts Extension instances to add to.
996 *
997 * @return LY_ERR values.
998 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200999static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001000parse_revisiondate(struct lys_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001001{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001002 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001003 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001004 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001005 enum yang_keyword kw;
1006
1007 if (rev[0]) {
David Sedlákb3077192019-06-19 10:55:37 +02001008 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001009 return LY_EVALID;
1010 }
1011
1012 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001013 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001014
1015 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001016 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001017 free(buf);
1018 return LY_EVALID;
1019 }
1020
1021 /* store value and spend buf if allocated */
1022 strncpy(rev, word, word_len);
1023 free(buf);
1024
Radek Krejci6d6556c2018-11-08 09:37:45 +01001025 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001026 switch (kw) {
1027 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001028 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001029 break;
1030 default:
David Sedlákb3077192019-06-19 10:55:37 +02001031 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001032 return LY_EVALID;
1033 }
1034 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001035 return ret;
1036}
1037
Michal Vaskoea5abea2018-09-18 13:10:54 +02001038/**
1039 * @brief Parse the include statement.
1040 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001041 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001042 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001043 * @param[in,out] data Data to read from, always moved to currently handled character.
1044 * @param[in,out] includes Parsed includes to add to.
1045 *
1046 * @return LY_ERR values.
1047 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001048static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001049parse_include(struct lys_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001050{
Radek Krejcid33273d2018-10-25 14:55:52 +02001051 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001052 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001053 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001054 enum yang_keyword kw;
1055 struct lysp_include *inc;
1056
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001057 LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001058
1059 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001060 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001061
Radek Krejci086c7132018-10-26 15:29:04 +02001062 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1063
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001064 /* submodules share the namespace with the module names, so there must not be
1065 * a module of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001066 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
David Sedlákb3077192019-06-19 10:55:37 +02001067 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001068 return LY_EVALID;
1069 }
1070
Radek Krejci6d6556c2018-11-08 09:37:45 +01001071 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001072 switch (kw) {
1073 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001074 YANG_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001075 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 +02001076 break;
1077 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001078 YANG_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001079 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 +02001080 break;
1081 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001082 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001083 break;
1084 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001085 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001086 break;
1087 default:
David Sedlákb3077192019-06-19 10:55:37 +02001088 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001089 return LY_EVALID;
1090 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001091 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001092 return ret;
1093}
1094
Michal Vaskoea5abea2018-09-18 13:10:54 +02001095/**
1096 * @brief Parse the import statement.
1097 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001098 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001099 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001100 * @param[in,out] data Data to read from, always moved to currently handled character.
1101 * @param[in,out] imports Parsed imports to add to.
1102 *
1103 * @return LY_ERR values.
1104 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001105static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001106parse_import(struct lys_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001107{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001108 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001109 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001110 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001111 enum yang_keyword kw;
1112 struct lysp_import *imp;
1113
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001114 LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001115
1116 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001117 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001118 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001119
Radek Krejci6d6556c2018-11-08 09:37:45 +01001120 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001121 switch (kw) {
1122 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001123 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 +01001124 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001125 break;
1126 case YANG_DESCRIPTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01001127 YANG_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001128 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 +02001129 break;
1130 case YANG_REFERENCE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001131 YANG_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001132 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 +02001133 break;
1134 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001135 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001136 break;
1137 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001138 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001139 break;
1140 default:
David Sedlákb3077192019-06-19 10:55:37 +02001141 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001142 return LY_EVALID;
1143 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001144 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001145 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001146checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001147 /* mandatory substatements */
David Sedlákb3077192019-06-19 10:55:37 +02001148 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001149
1150 return ret;
1151}
1152
Michal Vaskoea5abea2018-09-18 13:10:54 +02001153/**
1154 * @brief Parse the revision statement.
1155 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001156 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001157 * @param[in,out] data Data to read from, always moved to currently handled character.
1158 * @param[in,out] revs Parsed revisions to add to.
1159 *
1160 * @return LY_ERR values.
1161 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001162static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001163parse_revision(struct lys_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001164{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001165 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001166 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001167 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001168 enum yang_keyword kw;
1169 struct lysp_revision *rev;
1170
Radek Krejci2c4e7172018-10-19 15:56:26 +02001171 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001172
1173 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001174 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001175
1176 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001177 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001178 return LY_EVALID;
1179 }
1180
Radek Krejcib7db73a2018-10-24 14:18:40 +02001181 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001182 free(buf);
1183
Radek Krejci6d6556c2018-11-08 09:37:45 +01001184 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001185 switch (kw) {
1186 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001187 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 +02001188 break;
1189 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001190 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 +02001191 break;
1192 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001193 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001194 break;
1195 default:
David Sedlákb3077192019-06-19 10:55:37 +02001196 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001197 return LY_EVALID;
1198 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001199 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001200 return ret;
1201}
1202
Michal Vaskoea5abea2018-09-18 13:10:54 +02001203/**
1204 * @brief Parse a generic text field that can have more instances such as base.
1205 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001206 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001207 * @param[in,out] data Data to read from, always moved to currently handled character.
1208 * @param[in] substmt Type of this substatement.
1209 * @param[in,out] texts Parsed values to add to.
1210 * @param[in] arg Type of the expected argument.
1211 * @param[in,out] exts Extension instances to add to.
1212 *
1213 * @return LY_ERR values.
1214 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001215static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001216parse_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 +02001217 struct lysp_ext_instance **exts)
1218{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001219 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001220 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001221 const char **item;
1222 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001223 enum yang_keyword kw;
1224
1225 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001226 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001227
1228 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001229 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001230
Radek Krejci151a5b72018-10-19 14:21:44 +02001231 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001232 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001233 switch (kw) {
1234 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001235 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001236 break;
1237 default:
David Sedlákb3077192019-06-19 10:55:37 +02001238 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001239 return LY_EVALID;
1240 }
1241 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001242 return ret;
1243}
1244
Michal Vaskoea5abea2018-09-18 13:10:54 +02001245/**
1246 * @brief Parse the config statement.
1247 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001248 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001249 * @param[in,out] data Data to read from, always moved to currently handled character.
1250 * @param[in,out] flags Flags to add to.
1251 * @param[in,out] exts Extension instances to add to.
1252 *
1253 * @return LY_ERR values.
1254 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001255static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001256parse_config(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001257{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001258 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001259 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001260 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001261 enum yang_keyword kw;
1262
1263 if (*flags & LYS_CONFIG_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001264 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001265 return LY_EVALID;
1266 }
1267
1268 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001269 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001270
1271 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1272 *flags |= LYS_CONFIG_W;
1273 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1274 *flags |= LYS_CONFIG_R;
1275 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001276 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001277 free(buf);
1278 return LY_EVALID;
1279 }
1280 free(buf);
1281
Radek Krejci6d6556c2018-11-08 09:37:45 +01001282 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001283 switch (kw) {
1284 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001285 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001286 break;
1287 default:
David Sedlákb3077192019-06-19 10:55:37 +02001288 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001289 return LY_EVALID;
1290 }
1291 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001292 return ret;
1293}
1294
Michal Vaskoea5abea2018-09-18 13:10:54 +02001295/**
1296 * @brief Parse the mandatory statement.
1297 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001298 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001299 * @param[in,out] data Data to read from, always moved to currently handled character.
1300 * @param[in,out] flags Flags to add to.
1301 * @param[in,out] exts Extension instances to add to.
1302 *
1303 * @return LY_ERR values.
1304 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001305static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001306parse_mandatory(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001307{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001308 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001309 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001310 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001311 enum yang_keyword kw;
1312
1313 if (*flags & LYS_MAND_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001314 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001315 return LY_EVALID;
1316 }
1317
1318 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001319 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001320
1321 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1322 *flags |= LYS_MAND_TRUE;
1323 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1324 *flags |= LYS_MAND_FALSE;
1325 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001326 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001327 free(buf);
1328 return LY_EVALID;
1329 }
1330 free(buf);
1331
Radek Krejci6d6556c2018-11-08 09:37:45 +01001332 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001333 switch (kw) {
1334 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001335 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001336 break;
1337 default:
David Sedlákb3077192019-06-19 10:55:37 +02001338 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001339 return LY_EVALID;
1340 }
1341 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001342 return ret;
1343}
1344
Michal Vaskoea5abea2018-09-18 13:10:54 +02001345/**
1346 * @brief Parse a restriction such as range or length.
1347 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001348 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001349 * @param[in,out] data Data to read from, always moved to currently handled character.
1350 * @param[in] restr_kw Type of this particular restriction.
1351 * @param[in,out] exts Extension instances to add to.
1352 *
1353 * @return LY_ERR values.
1354 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001355static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001356parse_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 +02001357{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001358 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001359 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001360 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001361 enum yang_keyword kw;
1362
1363 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001364 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001365
David Sedlákb9b892c2019-07-12 14:44:02 +02001366 YANG_CHECK_NONEMPTY(ctx, word_len, ly_stmt2str(restr_kw));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001367 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001368 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001369 switch (kw) {
1370 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001371 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 +02001372 break;
1373 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001374 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 +02001375 break;
1376 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001377 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 +02001378 break;
1379 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001380 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 +02001381 break;
1382 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001383 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001384 break;
1385 default:
David Sedlákb3077192019-06-19 10:55:37 +02001386 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001387 return LY_EVALID;
1388 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001389 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001390 return ret;
1391}
1392
Michal Vaskoea5abea2018-09-18 13:10:54 +02001393/**
1394 * @brief Parse a restriction that can have more instances such as must.
1395 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001396 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001397 * @param[in,out] data Data to read from, always moved to currently handled character.
1398 * @param[in] restr_kw Type of this particular restriction.
1399 * @param[in,out] restrs Restrictions to add to.
1400 *
1401 * @return LY_ERR values.
1402 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001403static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001404parse_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 +02001405{
1406 struct lysp_restr *restr;
1407
Radek Krejci2c4e7172018-10-19 15:56:26 +02001408 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001409 return parse_restr(ctx, data, restr_kw, restr);
1410}
1411
Michal Vaskoea5abea2018-09-18 13:10:54 +02001412/**
1413 * @brief Parse the status statement.
1414 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001415 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001416 * @param[in,out] data Data to read from, always moved to currently handled character.
1417 * @param[in,out] flags Flags to add to.
1418 * @param[in,out] exts Extension instances to add to.
1419 *
1420 * @return LY_ERR values.
1421 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001422static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001423parse_status(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001424{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001425 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001426 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001427 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001428 enum yang_keyword kw;
1429
1430 if (*flags & LYS_STATUS_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001431 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001432 return LY_EVALID;
1433 }
1434
1435 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001436 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001437
1438 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1439 *flags |= LYS_STATUS_CURR;
1440 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1441 *flags |= LYS_STATUS_DEPRC;
1442 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1443 *flags |= LYS_STATUS_OBSLT;
1444 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001445 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001446 free(buf);
1447 return LY_EVALID;
1448 }
1449 free(buf);
1450
Radek Krejci6d6556c2018-11-08 09:37:45 +01001451 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001452 switch (kw) {
1453 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001454 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001455 break;
1456 default:
David Sedlákb3077192019-06-19 10:55:37 +02001457 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001458 return LY_EVALID;
1459 }
1460 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001461 return ret;
1462}
1463
Michal Vaskoea5abea2018-09-18 13:10:54 +02001464/**
1465 * @brief Parse the when statement.
1466 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001467 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001468 * @param[in,out] data Data to read from, always moved to currently handled character.
1469 * @param[in,out] when_p When pointer to parse to.
1470 *
1471 * @return LY_ERR values.
1472 */
Radek Krejcif09e4e82019-06-14 15:08:11 +02001473LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001474parse_when(struct lys_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001475{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001476 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001477 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001478 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001479 enum yang_keyword kw;
1480 struct lysp_when *when;
1481
1482 if (*when_p) {
David Sedlákb3077192019-06-19 10:55:37 +02001483 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001484 return LY_EVALID;
1485 }
1486
1487 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001488 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001489
1490 /* get value */
Radek Krejci2f54df52019-06-21 10:59:19 +02001491 LY_CHECK_ERR_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len), free(when), LY_EMEM);
David Sedlákb9b892c2019-07-12 14:44:02 +02001492 YANG_CHECK_NONEMPTY(ctx, word_len, "when");
Radek Krejci44ceedc2018-10-02 15:54:31 +02001493 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001494
Radek Krejcif09e4e82019-06-14 15:08:11 +02001495 *when_p = when;
1496
Radek Krejci6d6556c2018-11-08 09:37:45 +01001497 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001498 switch (kw) {
1499 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001500 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 +02001501 break;
1502 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001503 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 +02001504 break;
1505 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001506 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001507 break;
1508 default:
David Sedlákb3077192019-06-19 10:55:37 +02001509 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001510 return LY_EVALID;
1511 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001512 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001513 return ret;
1514}
1515
Michal Vaskoea5abea2018-09-18 13:10:54 +02001516/**
1517 * @brief Parse the anydata or anyxml statement.
1518 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001519 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001520 * @param[in,out] data Data to read from, always moved to currently handled character.
1521 * @param[in] kw Type of this particular keyword.
1522 * @param[in,out] siblings Siblings to add to.
1523 *
1524 * @return LY_ERR values.
1525 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02001526LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001527parse_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 +02001528{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001529 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001530 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001531 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001532 struct lysp_node *iter;
1533 struct lysp_node_anydata *any;
1534
1535 /* create structure */
1536 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001537 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001538 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001539 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001540
1541 /* insert into siblings */
1542 if (!*siblings) {
1543 *siblings = (struct lysp_node *)any;
1544 } else {
1545 for (iter = *siblings; iter->next; iter = iter->next);
1546 iter->next = (struct lysp_node *)any;
1547 }
1548
1549 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001550 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001551 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001552
1553 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001554 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001555 switch (kw) {
1556 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001557 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001558 break;
1559 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001560 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 +02001561 break;
1562 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001563 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 +02001564 break;
1565 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001566 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001567 break;
1568 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001569 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001570 break;
1571 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001572 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 +02001573 break;
1574 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001575 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001576 break;
1577 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001578 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001579 break;
1580 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001581 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001582 break;
1583 default:
David Sedlákb3077192019-06-19 10:55:37 +02001584 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001585 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001586 return LY_EVALID;
1587 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001588 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001589 return ret;
1590}
1591
Michal Vaskoea5abea2018-09-18 13:10:54 +02001592/**
1593 * @brief Parse the value or position statement. Substatement of type enum statement.
1594 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001595 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001596 * @param[in,out] data Data to read from, always moved to currently handled character.
1597 * @param[in] val_kw Type of this particular keyword.
1598 * @param[in,out] value Value to write to.
1599 * @param[in,out] flags Flags to write to.
1600 * @param[in,out] exts Extension instances to add to.
1601 *
1602 * @return LY_ERR values.
1603 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001604static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001605parse_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 +02001606 struct lysp_ext_instance **exts)
1607{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001608 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001609 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001610 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001611 long int num;
1612 unsigned long int unum;
1613 enum yang_keyword kw;
1614
1615 if (*flags & LYS_SET_VALUE) {
David Sedlákb3077192019-06-19 10:55:37 +02001616 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001617 return LY_EVALID;
1618 }
1619 *flags |= LYS_SET_VALUE;
1620
1621 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001622 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001623
1624 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 +02001625 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001626 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001627 }
1628
1629 errno = 0;
1630 if (val_kw == YANG_VALUE) {
1631 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001632 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlákb3077192019-06-19 10:55:37 +02001633 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001634 goto error;
1635 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001636 } else {
1637 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001638 if (unum > UINT64_C(4294967295)) {
David Sedlákb3077192019-06-19 10:55:37 +02001639 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001640 goto error;
1641 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001642 }
1643 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001644 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001645 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001646 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001647 }
1648 if (errno == ERANGE) {
David Sedlákb3077192019-06-19 10:55:37 +02001649 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001650 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001651 }
1652 if (val_kw == YANG_VALUE) {
1653 *value = num;
1654 } else {
1655 *value = unum;
1656 }
1657 free(buf);
1658
Radek Krejci6d6556c2018-11-08 09:37:45 +01001659 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001660 switch (kw) {
1661 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001662 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 +02001663 break;
1664 default:
David Sedlákb3077192019-06-19 10:55:37 +02001665 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001666 return LY_EVALID;
1667 }
1668 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001669 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001670
1671error:
1672 free(buf);
1673 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001674}
1675
Michal Vaskoea5abea2018-09-18 13:10:54 +02001676/**
1677 * @brief Parse the enum or bit statement. Substatement of type statement.
1678 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001679 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001680 * @param[in,out] data Data to read from, always moved to currently handled character.
1681 * @param[in] enum_kw Type of this particular keyword.
1682 * @param[in,out] enums Enums or bits to add to.
1683 *
1684 * @return LY_ERR values.
1685 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001686static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001687parse_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 +02001688{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001689 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001690 char *buf, *word;
David Sedlák6544c182019-07-12 13:17:33 +02001691 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001692 enum yang_keyword kw;
1693 struct lysp_type_enum *enm;
1694
Radek Krejci2c4e7172018-10-19 15:56:26 +02001695 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001696
1697 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001698 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 +01001699 if (enum_kw == YANG_ENUM) {
David Sedlák07869a52019-07-12 14:28:19 +02001700 ret = lysp_check_enum_name(ctx, (const char *)word, word_len);
David Sedlák6544c182019-07-12 13:17:33 +02001701 LY_CHECK_ERR_RET(ret, free(buf), ret);
Radek Krejci8b764662018-11-14 14:15:13 +01001702 } else { /* YANG_BIT */
1703
1704 }
Radek Krejcif09e4e82019-06-14 15:08:11 +02001705 if (enum_kw == YANG_ENUM) {
David Sedlákb9b892c2019-07-12 14:44:02 +02001706 YANG_CHECK_NONEMPTY(ctx, word_len, "enum");
Radek Krejcif09e4e82019-06-14 15:08:11 +02001707 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001708 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001709 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1710
Radek Krejci6d6556c2018-11-08 09:37:45 +01001711 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001712 switch (kw) {
1713 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001714 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 +02001715 break;
1716 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01001717 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001718 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 +02001719 break;
1720 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001721 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 +02001722 break;
1723 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001724 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001725 break;
1726 case YANG_VALUE:
David Sedlák9fb515f2019-07-11 10:33:58 +02001727 LY_CHECK_ERR_RET(enum_kw == YANG_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
1728 ly_stmt2str(enum_kw)), LY_EVALID);
1729 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
1730 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001731 case YANG_POSITION:
David Sedlák9fb515f2019-07-11 10:33:58 +02001732 LY_CHECK_ERR_RET(enum_kw == YANG_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
1733 ly_stmt2str(enum_kw)), LY_EVALID);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001734 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001735 break;
1736 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001737 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001738 break;
1739 default:
David Sedlákb3077192019-06-19 10:55:37 +02001740 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001741 return LY_EVALID;
1742 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001743 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001744 return ret;
1745}
1746
Michal Vaskoea5abea2018-09-18 13:10:54 +02001747/**
1748 * @brief Parse the fraction-digits statement. Substatement of type statement.
1749 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001750 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001751 * @param[in,out] data Data to read from, always moved to currently handled character.
1752 * @param[in,out] fracdig Value to write to.
1753 * @param[in,out] exts Extension instances to add to.
1754 *
1755 * @return LY_ERR values.
1756 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001757static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001758parse_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 +02001759{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001760 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001761 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001762 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001763 unsigned long int num;
1764 enum yang_keyword kw;
1765
1766 if (*fracdig) {
David Sedlákb3077192019-06-19 10:55:37 +02001767 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001768 return LY_EVALID;
1769 }
1770
1771 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001772 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001773
1774 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
David Sedlákb3077192019-06-19 10:55:37 +02001775 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001776 free(buf);
1777 return LY_EVALID;
1778 }
1779
1780 errno = 0;
1781 num = strtoul(word, &ptr, 10);
1782 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001783 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001784 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001785 free(buf);
1786 return LY_EVALID;
1787 }
1788 if ((errno == ERANGE) || (num > 18)) {
David Sedlákb3077192019-06-19 10:55:37 +02001789 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001790 free(buf);
1791 return LY_EVALID;
1792 }
1793 *fracdig = num;
1794 free(buf);
1795
Radek Krejci6d6556c2018-11-08 09:37:45 +01001796 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001797 switch (kw) {
1798 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001799 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001800 break;
1801 default:
David Sedlákb3077192019-06-19 10:55:37 +02001802 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001803 return LY_EVALID;
1804 }
1805 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001806 return ret;
1807}
1808
Michal Vaskoea5abea2018-09-18 13:10:54 +02001809/**
1810 * @brief Parse the require-instance statement. Substatement of type statement.
1811 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001812 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001813 * @param[in,out] data Data to read from, always moved to currently handled character.
1814 * @param[in,out] reqinst Value to write to.
1815 * @param[in,out] flags Flags to write to.
1816 * @param[in,out] exts Extension instances to add to.
1817 *
1818 * @return LY_ERR values.
1819 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001820static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001821parse_type_reqinstance(struct lys_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001822 struct lysp_ext_instance **exts)
1823{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001824 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001825 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001826 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001827 enum yang_keyword kw;
1828
1829 if (*flags & LYS_SET_REQINST) {
David Sedlákb3077192019-06-19 10:55:37 +02001830 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001831 return LY_EVALID;
1832 }
1833 *flags |= LYS_SET_REQINST;
1834
1835 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001836 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001837
1838 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1839 *reqinst = 1;
1840 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02001841 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001842 free(buf);
1843 return LY_EVALID;
1844 }
1845 free(buf);
1846
Radek Krejci6d6556c2018-11-08 09:37:45 +01001847 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001848 switch (kw) {
1849 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001850 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001851 break;
1852 default:
David Sedlákb3077192019-06-19 10:55:37 +02001853 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001854 return LY_EVALID;
1855 }
1856 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001857 return ret;
1858}
1859
Michal Vaskoea5abea2018-09-18 13:10:54 +02001860/**
1861 * @brief Parse the modifier statement. Substatement of type pattern statement.
1862 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001863 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001864 * @param[in,out] data Data to read from, always moved to currently handled character.
1865 * @param[in,out] pat Value to write to.
1866 * @param[in,out] exts Extension instances to add to.
1867 *
1868 * @return LY_ERR values.
1869 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001870static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001871parse_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 +02001872{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001873 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001874 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001875 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001876 enum yang_keyword kw;
1877
1878 if ((*pat)[0] == 0x15) {
David Sedlákb3077192019-06-19 10:55:37 +02001879 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001880 return LY_EVALID;
1881 }
1882
1883 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001884 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001885
1886 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02001887 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001888 free(buf);
1889 return LY_EVALID;
1890 }
1891 free(buf);
1892
1893 /* replace the value in the dictionary */
1894 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001895 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001896 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001897 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001898
1899 assert(buf[0] == 0x06);
1900 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02001901 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001902
Radek Krejci6d6556c2018-11-08 09:37:45 +01001903 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001904 switch (kw) {
1905 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001906 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001907 break;
1908 default:
David Sedlákb3077192019-06-19 10:55:37 +02001909 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001910 return LY_EVALID;
1911 }
1912 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001913 return ret;
1914}
1915
Michal Vaskoea5abea2018-09-18 13:10:54 +02001916/**
1917 * @brief Parse the pattern statement. Substatement of type statement.
1918 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001919 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001920 * @param[in,out] data Data to read from, always moved to currently handled character.
1921 * @param[in,out] patterns Restrictions to add to.
1922 *
1923 * @return LY_ERR values.
1924 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001925static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001926parse_type_pattern(struct lys_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001927{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001928 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001929 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001930 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001931 enum yang_keyword kw;
1932 struct lysp_restr *restr;
1933
Radek Krejci2c4e7172018-10-19 15:56:26 +02001934 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001935
1936 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001937 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001938
1939 /* add special meaning first byte */
1940 if (buf) {
1941 buf = realloc(buf, word_len + 2);
1942 word = buf;
1943 } else {
1944 buf = malloc(word_len + 2);
1945 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001946 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02001947 memmove(buf + 1, word, word_len);
1948 buf[0] = 0x06; /* pattern's default regular-match flag */
1949 buf[word_len + 1] = '\0'; /* terminating NULL byte */
1950 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001951
Radek Krejci6d6556c2018-11-08 09:37:45 +01001952 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001953 switch (kw) {
1954 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001955 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 +02001956 break;
1957 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001958 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 +02001959 break;
1960 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001961 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 +02001962 break;
1963 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001964 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 +02001965 break;
1966 case YANG_MODIFIER:
Radek Krejciceaf2122019-01-02 15:03:26 +01001967 YANG_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001968 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001969 break;
1970 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001971 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001972 break;
1973 default:
David Sedlákb3077192019-06-19 10:55:37 +02001974 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001975 return LY_EVALID;
1976 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001977 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001978 return ret;
1979}
1980
Michal Vaskoea5abea2018-09-18 13:10:54 +02001981/**
1982 * @brief Parse the type statement.
1983 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001984 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001985 * @param[in,out] data Data to read from, always moved to currently handled character.
1986 * @param[in,out] type Type to wrote to.
1987 *
1988 * @return LY_ERR values.
1989 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001990static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001991parse_type(struct lys_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001992{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001993 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001994 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001995 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001996 enum yang_keyword kw;
1997 struct lysp_type *nest_type;
1998
1999 if (type->name) {
David Sedlákb3077192019-06-19 10:55:37 +02002000 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002001 return LY_EVALID;
2002 }
2003
2004 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002005 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002006 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002007
Radek Krejci6d6556c2018-11-08 09:37:45 +01002008 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002009 switch (kw) {
2010 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002011 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 +01002012 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002013 break;
2014 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002015 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002016 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002017 break;
2018 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002019 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002020 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002021 break;
2022 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002023 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002024 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002025 break;
2026 case YANG_LENGTH:
2027 if (type->length) {
David Sedlákb3077192019-06-19 10:55:37 +02002028 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002029 return LY_EVALID;
2030 }
2031 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002032 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002033
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002034 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002035 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002036 break;
2037 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002038 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 +01002039 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002040 break;
2041 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002042 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002043 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002044 break;
2045 case YANG_RANGE:
2046 if (type->range) {
David Sedlákb3077192019-06-19 10:55:37 +02002047 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002048 return LY_EVALID;
2049 }
2050 type->range = calloc(1, sizeof *type->range);
David Sedlák7a8b2472019-07-11 15:08:34 +02002051 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002052
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002053 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002054 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002055 break;
2056 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002057 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002058 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002059 break;
2060 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002061 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2062 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002063 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002064 break;
2065 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002066 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002067 break;
2068 default:
David Sedlákb3077192019-06-19 10:55:37 +02002069 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002070 return LY_EVALID;
2071 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002072 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002073 return ret;
2074}
2075
Michal Vaskoea5abea2018-09-18 13:10:54 +02002076/**
2077 * @brief Parse the leaf statement.
2078 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002079 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002080 * @param[in,out] data Data to read from, always moved to currently handled character.
2081 * @param[in,out] siblings Siblings to add to.
2082 *
2083 * @return LY_ERR values.
2084 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002085LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002086parse_leaf(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002087{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002088 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002089 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002090 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002091 enum yang_keyword kw;
2092 struct lysp_node *iter;
2093 struct lysp_node_leaf *leaf;
2094
2095 /* create structure */
2096 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002097 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002098 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002099 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002100
2101 /* insert into siblings */
2102 if (!*siblings) {
2103 *siblings = (struct lysp_node *)leaf;
2104 } else {
2105 for (iter = *siblings; iter->next; iter = iter->next);
2106 iter->next = (struct lysp_node *)leaf;
2107 }
2108
2109 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002110 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002111 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002112
2113 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002114 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002115 switch (kw) {
2116 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002117 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002118 break;
2119 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002120 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 +02002121 break;
2122 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002123 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 +02002124 break;
2125 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002126 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 +02002127 break;
2128 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002129 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002130 break;
2131 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002132 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002133 break;
2134 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002135 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 +02002136 break;
2137 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002138 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002139 break;
2140 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002141 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002142 break;
2143 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002144 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 +02002145 break;
2146 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002147 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002148 break;
2149 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002150 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002151 break;
2152 default:
David Sedlákb3077192019-06-19 10:55:37 +02002153 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002154 return LY_EVALID;
2155 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002156 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002157 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002158checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002159 /* mandatory substatements */
2160 if (!leaf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002161 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002162 return LY_EVALID;
2163 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002164 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
David Sedlákb3077192019-06-19 10:55:37 +02002165 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002166 return LY_EVALID;
2167 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002168
2169 return ret;
2170}
2171
Michal Vaskoea5abea2018-09-18 13:10:54 +02002172/**
2173 * @brief Parse the max-elements statement.
2174 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002175 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002176 * @param[in,out] data Data to read from, always moved to currently handled character.
2177 * @param[in,out] max Value to write to.
2178 * @param[in,out] flags Flags to write to.
2179 * @param[in,out] exts Extension instances to add to.
2180 *
2181 * @return LY_ERR values.
2182 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002183LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002184parse_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 +02002185{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002186 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002187 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002188 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189 unsigned long int num;
2190 enum yang_keyword kw;
2191
2192 if (*flags & LYS_SET_MAX) {
David Sedlákb3077192019-06-19 10:55:37 +02002193 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002194 return LY_EVALID;
2195 }
2196 *flags |= LYS_SET_MAX;
2197
2198 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002199 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002200
2201 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
David Sedlákb3077192019-06-19 10:55:37 +02002202 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002203 free(buf);
2204 return LY_EVALID;
2205 }
2206
2207 if (strncmp(word, "unbounded", word_len)) {
2208 errno = 0;
2209 num = strtoul(word, &ptr, 10);
2210 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002211 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002212 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002213 free(buf);
2214 return LY_EVALID;
2215 }
2216 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002217 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002218 free(buf);
2219 return LY_EVALID;
2220 }
2221
2222 *max = num;
2223 }
2224 free(buf);
2225
Radek Krejci6d6556c2018-11-08 09:37:45 +01002226 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002227 switch (kw) {
2228 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002229 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002230 break;
2231 default:
David Sedlákb3077192019-06-19 10:55:37 +02002232 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002233 return LY_EVALID;
2234 }
2235 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002236 return ret;
2237}
2238
Michal Vaskoea5abea2018-09-18 13:10:54 +02002239/**
2240 * @brief Parse the min-elements statement.
2241 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002242 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002243 * @param[in,out] data Data to read from, always moved to currently handled character.
2244 * @param[in,out] min Value to write to.
2245 * @param[in,out] flags Flags to write to.
2246 * @param[in,out] exts Extension instances to add to.
2247 *
2248 * @return LY_ERR values.
2249 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002250LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002251parse_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 +02002252{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002253 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002254 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002255 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002256 unsigned long int num;
2257 enum yang_keyword kw;
2258
2259 if (*flags & LYS_SET_MIN) {
David Sedlákb3077192019-06-19 10:55:37 +02002260 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002261 return LY_EVALID;
2262 }
2263 *flags |= LYS_SET_MIN;
2264
2265 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002266 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002267
2268 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
David Sedlákb3077192019-06-19 10:55:37 +02002269 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002270 free(buf);
2271 return LY_EVALID;
2272 }
2273
2274 errno = 0;
2275 num = strtoul(word, &ptr, 10);
2276 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002277 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002278 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002279 free(buf);
2280 return LY_EVALID;
2281 }
2282 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002283 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002284 free(buf);
2285 return LY_EVALID;
2286 }
2287 *min = num;
2288 free(buf);
2289
Radek Krejci6d6556c2018-11-08 09:37:45 +01002290 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002291 switch (kw) {
2292 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002293 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002294 break;
2295 default:
David Sedlákb3077192019-06-19 10:55:37 +02002296 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002297 return LY_EVALID;
2298 }
2299 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002300 return ret;
2301}
2302
Michal Vaskoea5abea2018-09-18 13:10:54 +02002303/**
2304 * @brief Parse the ordered-by statement.
2305 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002306 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002307 * @param[in,out] data Data to read from, always moved to currently handled character.
2308 * @param[in,out] flags Flags to write to.
2309 * @param[in,out] exts Extension instances to add to.
2310 *
2311 * @return LY_ERR values.
2312 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002313static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002314parse_orderedby(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002315{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002316 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002317 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002318 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002319 enum yang_keyword kw;
2320
2321 if (*flags & LYS_ORDBY_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02002322 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002323 return LY_EVALID;
2324 }
2325
2326 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002327 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002328
2329 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2330 *flags |= LYS_ORDBY_SYSTEM;
2331 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2332 *flags |= LYS_ORDBY_USER;
2333 } else {
David Sedlákb3077192019-06-19 10:55:37 +02002334 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002335 free(buf);
2336 return LY_EVALID;
2337 }
2338 free(buf);
2339
Radek Krejci6d6556c2018-11-08 09:37:45 +01002340 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002341 switch (kw) {
2342 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002343 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002344 break;
2345 default:
David Sedlákb3077192019-06-19 10:55:37 +02002346 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002347 return LY_EVALID;
2348 }
2349 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002350 return ret;
2351}
2352
Michal Vaskoea5abea2018-09-18 13:10:54 +02002353/**
2354 * @brief Parse the leaf-list statement.
2355 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002356 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002357 * @param[in,out] data Data to read from, always moved to currently handled character.
2358 * @param[in,out] siblings Siblings to add to.
2359 *
2360 * @return LY_ERR values.
2361 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002362LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002363parse_leaflist(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002364{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002365 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002366 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002367 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002368 enum yang_keyword kw;
2369 struct lysp_node *iter;
2370 struct lysp_node_leaflist *llist;
2371
2372 /* create structure */
2373 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002374 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002375 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002376 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002377
2378 /* insert into siblings */
2379 if (!*siblings) {
2380 *siblings = (struct lysp_node *)llist;
2381 } else {
2382 for (iter = *siblings; iter->next; iter = iter->next);
2383 iter->next = (struct lysp_node *)llist;
2384 }
2385
2386 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002387 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002388 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002389
2390 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002391 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002392 switch (kw) {
2393 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002394 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002395 break;
2396 case YANG_DEFAULT:
Radek Krejciceaf2122019-01-02 15:03:26 +01002397 YANG_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002398 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 +02002399 break;
2400 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002401 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 +02002402 break;
2403 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002404 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 +02002405 break;
2406 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002407 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002408 break;
2409 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002410 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002411 break;
2412 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002413 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002414 break;
2415 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002416 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002417 break;
2418 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002419 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 +02002420 break;
2421 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002422 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002423 break;
2424 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002425 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002426 break;
2427 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002428 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 +02002429 break;
2430 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002431 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002432 break;
2433 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002434 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002435 break;
2436 default:
David Sedlákb3077192019-06-19 10:55:37 +02002437 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002438 return LY_EVALID;
2439 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002440 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002441 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002442checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002443 /* mandatory substatements */
2444 if (!llist->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002445 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002446 return LY_EVALID;
2447 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002448 if ((llist->min) && (llist->dflts)) {
David Sedlákb3077192019-06-19 10:55:37 +02002449 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
Radek Krejci0e5d8382018-11-28 16:37:53 +01002450 return LY_EVALID;
2451 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002452 if (llist->max && llist->min > llist->max) {
David Sedlákb3077192019-06-19 10:55:37 +02002453 LOGVAL_PARSER(ctx, LYVE_SEMANTICS,
Radek Krejcidf6cad12018-11-28 17:10:55 +01002454 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2455 llist->min, llist->max);
2456 return LY_EVALID;
2457 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002458
2459 return ret;
2460}
2461
Michal Vaskoea5abea2018-09-18 13:10:54 +02002462/**
2463 * @brief Parse the refine statement.
2464 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002465 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002466 * @param[in,out] data Data to read from, always moved to currently handled character.
2467 * @param[in,out] refines Refines to add to.
2468 *
2469 * @return LY_ERR values.
2470 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002471static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002472parse_refine(struct lys_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002473{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002474 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002475 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002476 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002477 enum yang_keyword kw;
2478 struct lysp_refine *rf;
2479
Radek Krejci2c4e7172018-10-19 15:56:26 +02002480 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002481
2482 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002483 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
David Sedlákb9b892c2019-07-12 14:44:02 +02002484 YANG_CHECK_NONEMPTY(ctx, word_len, "refine");
Radek Krejci44ceedc2018-10-02 15:54:31 +02002485 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002486
Radek Krejci6d6556c2018-11-08 09:37:45 +01002487 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002488 switch (kw) {
2489 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002490 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002491 break;
2492 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002493 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 +02002494 break;
2495 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002496 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 +02002497 break;
2498 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01002499 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002500 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 +02002501 break;
2502 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002503 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002504 break;
2505 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002506 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002507 break;
2508 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002509 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002510 break;
2511 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002512 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002513 break;
2514 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002515 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 +02002516 break;
2517 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002518 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 +02002519 break;
2520 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002521 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002522 break;
2523 default:
David Sedlákb3077192019-06-19 10:55:37 +02002524 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002525 return LY_EVALID;
2526 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002527 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002528 return ret;
2529}
2530
Michal Vaskoea5abea2018-09-18 13:10:54 +02002531/**
2532 * @brief Parse the typedef statement.
2533 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002534 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002535 * @param[in,out] data Data to read from, always moved to currently handled character.
2536 * @param[in,out] typedefs Typedefs to add to.
2537 *
2538 * @return LY_ERR values.
2539 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002540static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002541parse_typedef(struct lys_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002542{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002543 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002544 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002545 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002546 enum yang_keyword kw;
2547 struct lysp_tpdf *tpdf;
2548
Radek Krejci2c4e7172018-10-19 15:56:26 +02002549 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002550
2551 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002552 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002553 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002554
2555 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002556 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002557 switch (kw) {
2558 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002559 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 +02002560 break;
2561 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002562 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 +02002563 break;
2564 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002565 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 +02002566 break;
2567 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002568 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002569 break;
2570 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002571 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002572 break;
2573 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002574 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 +02002575 break;
2576 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002577 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002578 break;
2579 default:
David Sedlákb3077192019-06-19 10:55:37 +02002580 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002581 return LY_EVALID;
2582 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002583 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002584 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002585checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002586 /* mandatory substatements */
2587 if (!tpdf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002588 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002589 return LY_EVALID;
2590 }
2591
Radek Krejcibbe09a92018-11-08 09:36:54 +01002592 /* store data for collision check */
Radek Krejci7fc68292019-06-12 13:51:09 +02002593 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01002594 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2595 }
2596
Michal Vasko7fbc8162018-09-17 10:35:16 +02002597 return ret;
2598}
2599
Michal Vaskoea5abea2018-09-18 13:10:54 +02002600/**
2601 * @brief Parse the input or output statement.
2602 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002603 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002604 * @param[in,out] data Data to read from, always moved to currently handled character.
2605 * @param[in] kw Type of this particular keyword
2606 * @param[in,out] inout_p Input/output pointer to write to.
2607 *
2608 * @return LY_ERR values.
2609 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002610static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002611parse_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 +02002612{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002613 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002614 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002615 size_t word_len;
Radek Krejci10113652018-11-14 16:56:50 +01002616 enum yang_keyword kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002617
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002618 if (inout_p->nodetype) {
David Sedlákb3077192019-06-19 10:55:37 +02002619 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002620 return LY_EVALID;
2621 }
2622
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002623 /* initiate structure */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002624 inout_p->nodetype = &((struct lysp_action*)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002625 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002626
2627 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02002628 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002629 switch (kw) {
2630 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002631 YANG_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci10113652018-11-14 16:56:50 +01002632 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002633 case YANG_ANYXML:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002634 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002635 break;
2636 case YANG_CHOICE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002637 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002638 break;
2639 case YANG_CONTAINER:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002640 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002641 break;
2642 case YANG_LEAF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002643 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002644 break;
2645 case YANG_LEAF_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002646 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002647 break;
2648 case YANG_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002649 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002650 break;
2651 case YANG_USES:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002652 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002653 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002654 case YANG_TYPEDEF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002655 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002656 break;
2657 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01002658 YANG_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002659 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002660 break;
2661 case YANG_GROUPING:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002662 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002663 break;
2664 case YANG_CUSTOM:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002665 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002666 break;
2667 default:
David Sedlákb3077192019-06-19 10:55:37 +02002668 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002669 return LY_EVALID;
2670 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002671 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002672 LY_CHECK_RET(ret);
2673checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002674 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02002675 LY_CHECK_RET(parse_finalize_reallocated(ctx, inout_p->groupings, NULL, NULL, NULL));
2676
Michal Vasko7fbc8162018-09-17 10:35:16 +02002677 return ret;
2678}
2679
Michal Vaskoea5abea2018-09-18 13:10:54 +02002680/**
2681 * @brief Parse the action statement.
2682 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002683 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002684 * @param[in,out] data Data to read from, always moved to currently handled character.
2685 * @param[in,out] actions Actions to add to.
2686 *
2687 * @return LY_ERR values.
2688 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002689LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002690parse_action(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002691{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002692 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002693 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002694 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002695 enum yang_keyword kw;
2696 struct lysp_action *act;
2697
Radek Krejci2c4e7172018-10-19 15:56:26 +02002698 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002699
2700 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002701 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002702 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002703 act->nodetype = LYS_ACTION;
2704 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002705
Radek Krejci7fc68292019-06-12 13:51:09 +02002706 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002707 switch (kw) {
2708 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002709 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 +02002710 break;
2711 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002712 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 +02002713 break;
2714 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002715 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 +02002716 break;
2717 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002718 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002719 break;
2720
2721 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002722 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002723 break;
2724 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002725 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002726 break;
2727
2728 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002729 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002730 break;
2731 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002732 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002733 break;
2734 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002735 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002736 break;
2737 default:
David Sedlákb3077192019-06-19 10:55:37 +02002738 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002739 return LY_EVALID;
2740 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002741 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002742 LY_CHECK_RET(ret);
2743checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002744 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02002745 LY_CHECK_RET(parse_finalize_reallocated(ctx, act->groupings, NULL, NULL, NULL));
2746
Michal Vasko7fbc8162018-09-17 10:35:16 +02002747 return ret;
2748}
2749
Michal Vaskoea5abea2018-09-18 13:10:54 +02002750/**
2751 * @brief Parse the notification statement.
2752 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002753 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002754 * @param[in,out] data Data to read from, always moved to currently handled character.
2755 * @param[in,out] notifs Notifications to add to.
2756 *
2757 * @return LY_ERR values.
2758 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002759LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002760parse_notif(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002761{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002762 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002763 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002764 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002765 enum yang_keyword kw;
2766 struct lysp_notif *notif;
2767
Radek Krejci2c4e7172018-10-19 15:56:26 +02002768 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002769
2770 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002771 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002772 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002773 notif->nodetype = LYS_NOTIF;
2774 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002775
Radek Krejci7fc68292019-06-12 13:51:09 +02002776 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002777 switch (kw) {
2778 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002779 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 +02002780 break;
2781 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002782 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 +02002783 break;
2784 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002785 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 +02002786 break;
2787 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002788 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002789 break;
2790
2791 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002792 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci10113652018-11-14 16:56:50 +01002793 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002794 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002795 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 break;
2797 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002798 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002799 break;
2800 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002801 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002802 break;
2803 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002804 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002805 break;
2806 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002807 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002808 break;
2809 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002810 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002811 break;
2812 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002813 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002814 break;
2815
2816 case YANG_MUST:
Radek Krejciceaf2122019-01-02 15:03:26 +01002817 YANG_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002818 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002819 break;
2820 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002821 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002822 break;
2823 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002824 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002825 break;
2826 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002827 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002828 break;
2829 default:
David Sedlákb3077192019-06-19 10:55:37 +02002830 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002831 return LY_EVALID;
2832 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002833 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002834 LY_CHECK_RET(ret);
2835checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002836 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02002837 LY_CHECK_RET(parse_finalize_reallocated(ctx, notif->groupings, NULL, NULL, NULL));
2838
Michal Vasko7fbc8162018-09-17 10:35:16 +02002839 return ret;
2840}
2841
Michal Vaskoea5abea2018-09-18 13:10:54 +02002842/**
2843 * @brief Parse the grouping statement.
2844 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002845 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002846 * @param[in,out] data Data to read from, always moved to currently handled character.
2847 * @param[in,out] groupings Groupings to add to.
2848 *
2849 * @return LY_ERR values.
2850 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002851LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002852parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002853{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002854 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002855 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002856 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 enum yang_keyword kw;
2858 struct lysp_grp *grp;
2859
Radek Krejci2c4e7172018-10-19 15:56:26 +02002860 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002861
2862 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002863 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002864 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002865 grp->nodetype = LYS_GROUPING;
2866 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002867
Radek Krejci7fc68292019-06-12 13:51:09 +02002868 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002869 switch (kw) {
2870 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002871 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 +02002872 break;
2873 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002874 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 +02002875 break;
2876 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002877 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002878 break;
2879
2880 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002881 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci10113652018-11-14 16:56:50 +01002882 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002883 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002884 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002885 break;
2886 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002887 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002888 break;
2889 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002890 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002891 break;
2892 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002893 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002894 break;
2895 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002896 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002897 break;
2898 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002899 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002900 break;
2901 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002902 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002903 break;
2904
2905 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002906 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002907 break;
2908 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01002909 YANG_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002910 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002911 break;
2912 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002913 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002914 break;
2915 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01002916 YANG_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002917 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002918 break;
2919 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002920 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002921 break;
2922 default:
David Sedlákb3077192019-06-19 10:55:37 +02002923 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002924 return LY_EVALID;
2925 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002926 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002927 LY_CHECK_RET(ret);
2928checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002929 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02002930 LY_CHECK_RET(parse_finalize_reallocated(ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2931
Michal Vasko7fbc8162018-09-17 10:35:16 +02002932 return ret;
2933}
2934
Michal Vaskoea5abea2018-09-18 13:10:54 +02002935/**
2936 * @brief Parse the refine statement.
2937 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002938 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002939 * @param[in,out] data Data to read from, always moved to currently handled character.
2940 * @param[in,out] augments Augments to add to.
2941 *
2942 * @return LY_ERR values.
2943 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002944LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002945parse_augment(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002946{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002947 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002948 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002949 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002950 enum yang_keyword kw;
2951 struct lysp_augment *aug;
2952
Radek Krejci2c4e7172018-10-19 15:56:26 +02002953 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002954
2955 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002956 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
David Sedlákb9b892c2019-07-12 14:44:02 +02002957 YANG_CHECK_NONEMPTY(ctx, word_len, "augment");
Radek Krejci44ceedc2018-10-02 15:54:31 +02002958 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002959 aug->nodetype = LYS_AUGMENT;
2960 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002961
Radek Krejci7fc68292019-06-12 13:51:09 +02002962 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002963 switch (kw) {
2964 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002965 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 +02002966 break;
2967 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002968 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 +02002969 break;
2970 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002971 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 +02002972 break;
2973 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002974 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002975 break;
2976 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002977 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978 break;
2979
2980 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01002981 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci10113652018-11-14 16:56:50 +01002982 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002983 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002984 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002985 break;
2986 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002987 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002988 break;
2989 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002990 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002991 break;
2992 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002993 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002994 break;
2995 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002996 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002997 break;
2998 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002999 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003000 break;
3001 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003002 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003003 break;
3004 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003005 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003006 break;
3007
3008 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003009 YANG_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003010 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003011 break;
3012 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003013 YANG_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003014 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003015 break;
3016 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003017 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003018 break;
3019 default:
David Sedlákb3077192019-06-19 10:55:37 +02003020 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003021 return LY_EVALID;
3022 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003023 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003024 LY_CHECK_RET(ret);
3025checks:
3026 /* finalize parent pointers to the reallocated items */
3027 LY_CHECK_RET(parse_finalize_reallocated(ctx, NULL, NULL, aug->actions, aug->notifs));
3028
Michal Vasko7fbc8162018-09-17 10:35:16 +02003029 return ret;
3030}
3031
Michal Vaskoea5abea2018-09-18 13:10:54 +02003032/**
Radek Krejci7fc68292019-06-12 13:51:09 +02003033 * @brief Finalize some of the structures in case they are stored in sized array,
3034 * which can be possibly reallocated and some other data may point to them.
3035 *
3036 * Update parent pointers in the nodes inside grouping/augment/RPC/Notification, which could be reallocated.
3037 *
3038 * @param[in] mod Parsed module to be updated.
3039 * @return LY_ERR value (currently only LY_SUCCESS, but it can change in future).
3040 */
3041static LY_ERR
3042parse_finalize_reallocated(struct lys_parser_ctx *ctx, struct lysp_grp *groupings, struct lysp_augment *augments,
3043 struct lysp_action *actions, struct lysp_notif *notifs)
3044{
3045 unsigned int u, v;
3046 struct lysp_node *child;
3047
3048 /* finalize parent pointers to the reallocated items */
3049
3050 /* gropings */
3051 LY_ARRAY_FOR(groupings, u) {
3052 LY_LIST_FOR(groupings[u].data, child) {
3053 child->parent = (struct lysp_node*)&groupings[u];
3054 }
3055 LY_ARRAY_FOR(groupings[u].actions, v) {
3056 groupings[u].actions[v].parent = (struct lysp_node*)&groupings[u];
3057 }
3058 LY_ARRAY_FOR(groupings[u].notifs, v) {
3059 groupings[u].notifs[v].parent = (struct lysp_node*)&groupings[u];
3060 }
3061 LY_ARRAY_FOR(groupings[u].groupings, v) {
3062 groupings[u].groupings[v].parent = (struct lysp_node*)&groupings[u];
3063 }
3064 if (groupings[u].typedefs) {
3065 ly_set_add(&ctx->tpdfs_nodes, &groupings[u], 0);
3066 }
3067 }
3068
3069 /* augments */
3070 LY_ARRAY_FOR(augments, u) {
3071 LY_LIST_FOR(augments[u].child, child) {
3072 child->parent = (struct lysp_node*)&augments[u];
3073 }
3074 LY_ARRAY_FOR(augments[u].actions, v) {
3075 augments[u].actions[v].parent = (struct lysp_node*)&augments[u];
3076 }
3077 LY_ARRAY_FOR(augments[u].notifs, v) {
3078 augments[u].notifs[v].parent = (struct lysp_node*)&augments[u];
3079 }
3080 }
3081
3082 /* actions */
3083 LY_ARRAY_FOR(actions, u) {
3084 if (actions[u].input.parent) {
3085 actions[u].input.parent = (struct lysp_node*)&actions[u];
3086 LY_LIST_FOR(actions[u].input.data, child) {
3087 child->parent = (struct lysp_node*)&actions[u].input;
3088 }
3089 LY_ARRAY_FOR(actions[u].input.groupings, v) {
3090 actions[u].input.groupings[v].parent = (struct lysp_node*)&actions[u].input;
3091 }
3092 if (actions[u].input.typedefs) {
3093 ly_set_add(&ctx->tpdfs_nodes, &actions[u].input, 0);
3094 }
3095 }
3096 if (actions[u].output.parent) {
3097 actions[u].output.parent = (struct lysp_node*)&actions[u];
3098 LY_LIST_FOR(actions[u].output.data, child) {
3099 child->parent = (struct lysp_node*)&actions[u].output;
3100 }
3101 LY_ARRAY_FOR(actions[u].output.groupings, v) {
3102 actions[u].output.groupings[v].parent = (struct lysp_node*)&actions[u].output;
3103 }
3104 if (actions[u].output.typedefs) {
3105 ly_set_add(&ctx->tpdfs_nodes, &actions[u].output, 0);
3106 }
3107 }
3108 LY_ARRAY_FOR(actions[u].groupings, v) {
3109 actions[u].groupings[v].parent = (struct lysp_node*)&actions[u];
3110 }
3111 if (actions[u].typedefs) {
3112 ly_set_add(&ctx->tpdfs_nodes, &actions[u], 0);
3113 }
3114 }
3115
3116 /* notifications */
3117 LY_ARRAY_FOR(notifs, u) {
3118 LY_LIST_FOR(notifs[u].data, child) {
3119 child->parent = (struct lysp_node*)&notifs[u];
3120 }
3121 LY_ARRAY_FOR(notifs[u].groupings, v) {
3122 notifs[u].groupings[v].parent = (struct lysp_node*)&notifs[u];
3123 }
3124 if (notifs[u].typedefs) {
3125 ly_set_add(&ctx->tpdfs_nodes, &notifs[u], 0);
3126 }
3127 }
3128
3129 return LY_SUCCESS;
3130}
3131
3132/**
Michal Vaskoea5abea2018-09-18 13:10:54 +02003133 * @brief Parse the uses statement.
3134 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003135 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003136 * @param[in,out] data Data to read from, always moved to currently handled character.
3137 * @param[in,out] siblings Siblings to add to.
3138 *
3139 * @return LY_ERR values.
3140 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003141LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003142parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003143{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003144 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003145 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003146 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003147 enum yang_keyword kw;
3148 struct lysp_node *iter;
3149 struct lysp_node_uses *uses;
3150
3151 /* create structure */
3152 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003153 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003154 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003155 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003156
3157 /* insert into siblings */
3158 if (!*siblings) {
3159 *siblings = (struct lysp_node *)uses;
3160 } else {
3161 for (iter = *siblings; iter->next; iter = iter->next);
3162 iter->next = (struct lysp_node *)uses;
3163 }
3164
3165 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003166 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003167 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003168
3169 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003170 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003171 switch (kw) {
3172 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003173 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 +02003174 break;
3175 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003176 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 +02003177 break;
3178 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003179 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 +02003180 break;
3181 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003182 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003183 break;
3184 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003185 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003186 break;
3187
3188 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003189 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003190 break;
3191 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003192 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003193 break;
3194 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003195 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003196 break;
3197 default:
David Sedlákb3077192019-06-19 10:55:37 +02003198 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003199 return LY_EVALID;
3200 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003201 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003202checks:
3203 /* finalize parent pointers to the reallocated items */
3204 LY_CHECK_RET(parse_finalize_reallocated(ctx, NULL, uses->augments, NULL, NULL));
3205
Michal Vasko7fbc8162018-09-17 10:35:16 +02003206 return ret;
3207}
3208
Michal Vaskoea5abea2018-09-18 13:10:54 +02003209/**
3210 * @brief Parse the case statement.
3211 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003212 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003213 * @param[in,out] data Data to read from, always moved to currently handled character.
3214 * @param[in,out] siblings Siblings to add to.
3215 *
3216 * @return LY_ERR values.
3217 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003218LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003219parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003220{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003221 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003222 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003223 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224 enum yang_keyword kw;
3225 struct lysp_node *iter;
3226 struct lysp_node_case *cas;
3227
3228 /* create structure */
3229 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003230 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003231 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003232 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003233
3234 /* insert into siblings */
3235 if (!*siblings) {
3236 *siblings = (struct lysp_node *)cas;
3237 } else {
3238 for (iter = *siblings; iter->next; iter = iter->next);
3239 iter->next = (struct lysp_node *)cas;
3240 }
3241
3242 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003243 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003244 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003245
3246 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003247 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003248 switch (kw) {
3249 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003250 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 +02003251 break;
3252 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003253 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 +02003254 break;
3255 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003256 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 +02003257 break;
3258 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003259 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003260 break;
3261 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003262 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003263 break;
3264
3265 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003266 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci10113652018-11-14 16:56:50 +01003267 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003268 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003269 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003270 break;
3271 case YANG_CHOICE:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003272 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003273 break;
3274 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003275 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003276 break;
3277 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003278 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003279 break;
3280 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003281 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003282 break;
3283 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003284 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003285 break;
3286 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003287 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003288 break;
3289 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003290 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003291 break;
3292 default:
David Sedlákb3077192019-06-19 10:55:37 +02003293 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003294 return LY_EVALID;
3295 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003296 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297 return ret;
3298}
3299
Michal Vaskoea5abea2018-09-18 13:10:54 +02003300/**
3301 * @brief Parse the choice statement.
3302 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003303 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003304 * @param[in,out] data Data to read from, always moved to currently handled character.
3305 * @param[in,out] siblings Siblings to add to.
3306 *
3307 * @return LY_ERR values.
3308 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003309LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003310parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003311{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003312 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003313 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003314 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003315 enum yang_keyword kw;
3316 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003317 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003318
3319 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003320 choice = calloc(1, sizeof *choice);
3321 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3322 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003323 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003324
3325 /* insert into siblings */
3326 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003327 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003328 } else {
3329 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003330 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003331 }
3332
3333 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003334 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003335 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003336
3337 /* parse substatements */
Radek Krejcia9026eb2018-12-12 16:04:47 +01003338 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003339 switch (kw) {
3340 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003341 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003342 break;
3343 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003344 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 +02003345 break;
3346 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003347 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 +02003348 break;
3349 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003350 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003351 break;
3352 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003353 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 +02003354 break;
3355 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003356 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003357 break;
3358 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003359 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003360 break;
3361 case YANG_DEFAULT:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003362 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 +02003363 break;
3364
3365 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003366 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci10113652018-11-14 16:56:50 +01003367 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003368 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003369 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003370 break;
3371 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003372 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003373 break;
3374 case YANG_CHOICE:
Radek Krejciceaf2122019-01-02 15:03:26 +01003375 YANG_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003376 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003377 break;
3378 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003379 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003380 break;
3381 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003382 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003383 break;
3384 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003385 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003386 break;
3387 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003388 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003389 break;
3390 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003391 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003392 break;
3393 default:
David Sedlákb3077192019-06-19 10:55:37 +02003394 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003395 return LY_EVALID;
3396 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003397 }
Radek Krejcia9026eb2018-12-12 16:04:47 +01003398 LY_CHECK_RET(ret);
3399checks:
3400 if ((choice->flags & LYS_MAND_TRUE) && choice->dflt) {
David Sedlákb3077192019-06-19 10:55:37 +02003401 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "choice");
Radek Krejcia9026eb2018-12-12 16:04:47 +01003402 return LY_EVALID;
3403 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003404 return ret;
3405}
3406
Michal Vaskoea5abea2018-09-18 13:10:54 +02003407/**
3408 * @brief Parse the container statement.
3409 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003410 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003411 * @param[in,out] data Data to read from, always moved to currently handled character.
3412 * @param[in,out] siblings Siblings to add to.
3413 *
3414 * @return LY_ERR values.
3415 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003416LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003417parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003418{
3419 LY_ERR ret = 0;
3420 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003421 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003422 enum yang_keyword kw;
3423 struct lysp_node *iter;
3424 struct lysp_node_container *cont;
3425
3426 /* create structure */
3427 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003428 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003429 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003430 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003431
3432 /* insert into siblings */
3433 if (!*siblings) {
3434 *siblings = (struct lysp_node *)cont;
3435 } else {
3436 for (iter = *siblings; iter->next; iter = iter->next);
3437 iter->next = (struct lysp_node *)cont;
3438 }
3439
3440 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003441 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003442 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003443
3444 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003445 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003446 switch (kw) {
3447 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003448 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003449 break;
3450 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003451 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 +02003452 break;
3453 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003454 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 +02003455 break;
3456 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003457 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 +02003458 break;
3459 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003460 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003461 break;
3462 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003463 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003464 break;
3465 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003466 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 +02003467 break;
3468
3469 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003470 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci10113652018-11-14 16:56:50 +01003471 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003472 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003473 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003474 break;
3475 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003476 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003477 break;
3478 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003479 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003480 break;
3481 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003482 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003483 break;
3484 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003485 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003486 break;
3487 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003488 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003489 break;
3490 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003491 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003492 break;
3493
3494 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003495 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003496 break;
3497 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003498 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003499 break;
3500 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003501 YANG_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003502 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003503 break;
3504 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003505 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003506 break;
3507 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003508 YANG_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003509 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003510 break;
3511 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003512 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003513 break;
3514 default:
David Sedlákb3077192019-06-19 10:55:37 +02003515 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003516 return LY_EVALID;
3517 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003518 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003519checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003520 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02003521 LY_CHECK_RET(parse_finalize_reallocated(ctx, cont->groupings, NULL, cont->actions, cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003522 return ret;
3523}
3524
Michal Vaskoea5abea2018-09-18 13:10:54 +02003525/**
3526 * @brief Parse the list statement.
3527 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003528 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003529 * @param[in,out] data Data to read from, always moved to currently handled character.
3530 * @param[in,out] siblings Siblings to add to.
3531 *
3532 * @return LY_ERR values.
3533 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003534LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003535parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003536{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003537 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003538 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003539 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003540 enum yang_keyword kw;
3541 struct lysp_node *iter;
3542 struct lysp_node_list *list;
3543
3544 /* create structure */
3545 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003546 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003547 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003548 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003549
3550 /* insert into siblings */
3551 if (!*siblings) {
3552 *siblings = (struct lysp_node *)list;
3553 } else {
3554 for (iter = *siblings; iter->next; iter = iter->next);
3555 iter->next = (struct lysp_node *)list;
3556 }
3557
3558 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003559 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003560 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003561
3562 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003563 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003564 switch (kw) {
3565 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003566 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003567 break;
3568 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003569 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 +02003570 break;
3571 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003572 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 +02003573 break;
3574 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003575 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 +02003576 break;
3577 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003578 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003579 break;
3580 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003581 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003582 break;
3583 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003584 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 +02003585 break;
3586 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003587 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003588 break;
3589 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003590 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003591 break;
3592 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003593 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003594 break;
3595 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003596 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 +02003597 break;
3598
3599 case YANG_ANYDATA:
Radek Krejciceaf2122019-01-02 15:03:26 +01003600 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci10113652018-11-14 16:56:50 +01003601 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003602 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003603 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003604 break;
3605 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003606 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003607 break;
3608 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003609 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610 break;
3611 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003612 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003613 break;
3614 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003615 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003616 break;
3617 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003618 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003619 break;
3620 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003621 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003622 break;
3623
3624 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003625 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003626 break;
3627 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003628 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003629 break;
3630 case YANG_ACTION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003631 YANG_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003632 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003633 break;
3634 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003635 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003636 break;
3637 case YANG_NOTIFICATION:
Radek Krejciceaf2122019-01-02 15:03:26 +01003638 YANG_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003639 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003640 break;
3641 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003642 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643 break;
3644 default:
David Sedlákb3077192019-06-19 10:55:37 +02003645 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003646 return LY_EVALID;
3647 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003648 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003649 LY_CHECK_RET(ret);
3650checks:
Radek Krejci7fc68292019-06-12 13:51:09 +02003651 /* finalize parent pointers to the reallocated items */
3652 LY_CHECK_RET(parse_finalize_reallocated(ctx, list->groupings, NULL, list->actions, list->notifs));
3653
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003654 if (list->max && list->min > list->max) {
David Sedlákb3077192019-06-19 10:55:37 +02003655 LOGVAL_PARSER(ctx, LYVE_SEMANTICS,
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003656 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3657 list->min, list->max);
3658 return LY_EVALID;
3659 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003660
3661 return ret;
3662}
3663
Michal Vaskoea5abea2018-09-18 13:10:54 +02003664/**
3665 * @brief Parse the yin-element statement.
3666 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003667 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003668 * @param[in,out] data Data to read from, always moved to currently handled character.
3669 * @param[in,out] flags Flags to write to.
3670 * @param[in,out] exts Extension instances to add to.
3671 *
3672 * @return LY_ERR values.
3673 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003674static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003675parse_yinelement(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003676{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003677 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003678 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003679 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003680 enum yang_keyword kw;
3681
3682 if (*flags & LYS_YINELEM_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02003683 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003684 return LY_EVALID;
3685 }
3686
3687 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003688 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003689
3690 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3691 *flags |= LYS_YINELEM_TRUE;
3692 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3693 *flags |= LYS_YINELEM_FALSE;
3694 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003695 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003696 free(buf);
3697 return LY_EVALID;
3698 }
3699 free(buf);
3700
Radek Krejci6d6556c2018-11-08 09:37:45 +01003701 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003702 switch (kw) {
3703 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003704 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3705 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003706 default:
David Sedlákb3077192019-06-19 10:55:37 +02003707 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003708 return LY_EVALID;
3709 }
3710 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003711 return ret;
3712}
3713
Michal Vaskoea5abea2018-09-18 13:10:54 +02003714/**
David Sedlák2444f8f2019-07-09 11:02:47 +02003715 * @brief Parse the argument statement.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003716 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003717 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003718 * @param[in,out] data Data to read from, always moved to currently handled character.
3719 * @param[in,out] argument Value to write to.
3720 * @param[in,out] flags Flags to write to.
3721 * @param[in,out] exts Extension instances to add to.
3722 *
3723 * @return LY_ERR values.
3724 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003726parse_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 +02003727{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003728 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003729 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003730 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003731 enum yang_keyword kw;
3732
3733 if (*argument) {
David Sedlákb3077192019-06-19 10:55:37 +02003734 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003735 return LY_EVALID;
3736 }
3737
3738 /* get value */
David Sedlák2444f8f2019-07-09 11:02:47 +02003739 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003740 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003741
Radek Krejci6d6556c2018-11-08 09:37:45 +01003742 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003743 switch (kw) {
3744 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003745 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003746 break;
3747 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003748 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003749 break;
3750 default:
David Sedlákb3077192019-06-19 10:55:37 +02003751 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003752 return LY_EVALID;
3753 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003754 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003755 return ret;
3756}
3757
Michal Vaskoea5abea2018-09-18 13:10:54 +02003758/**
3759 * @brief Parse the extension statement.
3760 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003761 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003762 * @param[in,out] data Data to read from, always moved to currently handled character.
3763 * @param[in,out] extensions Extensions to add to.
3764 *
3765 * @return LY_ERR values.
3766 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003767static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003768parse_extension(struct lys_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003769{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003770 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003771 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003772 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003773 enum yang_keyword kw;
3774 struct lysp_ext *ex;
3775
Radek Krejci2c4e7172018-10-19 15:56:26 +02003776 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003777
3778 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003779 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003780 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003781
Radek Krejci6d6556c2018-11-08 09:37:45 +01003782 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003783 switch (kw) {
3784 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003785 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 +02003786 break;
3787 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003788 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 +02003789 break;
3790 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003791 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003792 break;
3793 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003794 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003795 break;
3796 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003797 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003798 break;
3799 default:
David Sedlákb3077192019-06-19 10:55:37 +02003800 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003801 return LY_EVALID;
3802 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003803 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003804 return ret;
3805}
3806
Michal Vaskoea5abea2018-09-18 13:10:54 +02003807/**
3808 * @brief Parse the deviate statement.
3809 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003810 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003811 * @param[in,out] data Data to read from, always moved to currently handled character.
3812 * @param[in,out] deviates Deviates to add to.
3813 *
3814 * @return LY_ERR values.
3815 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003816LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003817parse_deviate(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003818{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003819 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003820 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003821 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003822 enum yang_keyword kw;
3823 struct lysp_deviate *iter, *d;
3824 struct lysp_deviate_add *d_add = NULL;
3825 struct lysp_deviate_rpl *d_rpl = NULL;
3826 struct lysp_deviate_del *d_del = NULL;
3827 const char **d_units, ***d_uniques, ***d_dflts;
3828 struct lysp_restr **d_musts;
3829 uint16_t *d_flags;
3830 uint32_t *d_min, *d_max;
3831
3832 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003833 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003834
3835 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3836 dev_mod = LYS_DEV_NOT_SUPPORTED;
3837 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3838 dev_mod = LYS_DEV_ADD;
3839 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3840 dev_mod = LYS_DEV_REPLACE;
3841 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3842 dev_mod = LYS_DEV_DELETE;
3843 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003844 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003845 free(buf);
3846 return LY_EVALID;
3847 }
3848 free(buf);
3849
3850 /* create structure */
3851 switch (dev_mod) {
3852 case LYS_DEV_NOT_SUPPORTED:
3853 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003854 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003855 break;
3856 case LYS_DEV_ADD:
3857 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003858 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003859 d = (struct lysp_deviate *)d_add;
3860 d_units = &d_add->units;
3861 d_uniques = &d_add->uniques;
3862 d_dflts = &d_add->dflts;
3863 d_musts = &d_add->musts;
3864 d_flags = &d_add->flags;
3865 d_min = &d_add->min;
3866 d_max = &d_add->max;
3867 break;
3868 case LYS_DEV_REPLACE:
3869 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003870 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003871 d = (struct lysp_deviate *)d_rpl;
3872 d_units = &d_rpl->units;
3873 d_flags = &d_rpl->flags;
3874 d_min = &d_rpl->min;
3875 d_max = &d_rpl->max;
3876 break;
3877 case LYS_DEV_DELETE:
3878 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003879 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003880 d = (struct lysp_deviate *)d_del;
3881 d_units = &d_del->units;
3882 d_uniques = &d_del->uniques;
3883 d_dflts = &d_del->dflts;
3884 d_musts = &d_del->musts;
3885 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003886 break;
3887 default:
3888 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003889 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003890 }
3891 d->mod = dev_mod;
3892
3893 /* insert into siblings */
3894 if (!*deviates) {
3895 *deviates = d;
3896 } else {
3897 for (iter = *deviates; iter->next; iter = iter->next);
3898 iter->next = d;
3899 }
3900
Radek Krejci6d6556c2018-11-08 09:37:45 +01003901 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003902 switch (kw) {
3903 case YANG_CONFIG:
3904 switch (dev_mod) {
3905 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003906 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003907 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003908 return LY_EVALID;
3909 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003910 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003911 break;
3912 }
3913 break;
3914 case YANG_DEFAULT:
3915 switch (dev_mod) {
3916 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02003917 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003918 return LY_EVALID;
3919 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003920 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 +02003921 break;
3922 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003923 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 +02003924 break;
3925 }
3926 break;
3927 case YANG_MANDATORY:
3928 switch (dev_mod) {
3929 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003930 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003931 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003932 return LY_EVALID;
3933 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003934 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003935 break;
3936 }
3937 break;
3938 case YANG_MAX_ELEMENTS:
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_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003946 break;
3947 }
3948 break;
3949 case YANG_MIN_ELEMENTS:
3950 switch (dev_mod) {
3951 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003952 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003953 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003954 return LY_EVALID;
3955 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003956 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003957 break;
3958 }
3959 break;
3960 case YANG_MUST:
3961 switch (dev_mod) {
3962 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003963 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02003964 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003965 return LY_EVALID;
3966 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003967 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003968 break;
3969 }
3970 break;
3971 case YANG_TYPE:
3972 switch (dev_mod) {
3973 case LYS_DEV_NOT_SUPPORTED:
3974 case LYS_DEV_ADD:
3975 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003976 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003977 return LY_EVALID;
3978 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003979 if (d_rpl->type) {
David Sedlákb3077192019-06-19 10:55:37 +02003980 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003981 return LY_EVALID;
3982 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003983 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003984 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003985 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003986 break;
3987 }
3988 break;
3989 case YANG_UNIQUE:
3990 switch (dev_mod) {
3991 case LYS_DEV_NOT_SUPPORTED:
3992 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02003993 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003994 return LY_EVALID;
3995 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003996 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 +02003997 break;
3998 }
3999 break;
4000 case YANG_UNITS:
4001 switch (dev_mod) {
4002 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02004003 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004004 return LY_EVALID;
4005 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004006 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 +02004007 break;
4008 }
4009 break;
4010 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004011 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004012 break;
4013 default:
David Sedlákb3077192019-06-19 10:55:37 +02004014 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004015 return LY_EVALID;
4016 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004018 return ret;
4019}
4020
Michal Vaskoea5abea2018-09-18 13:10:54 +02004021/**
4022 * @brief Parse the deviation statement.
4023 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004024 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004025 * @param[in,out] data Data to read from, always moved to currently handled character.
4026 * @param[in,out] deviations Deviations to add to.
4027 *
4028 * @return LY_ERR values.
4029 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004030LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004031parse_deviation(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004032{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004033 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004034 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004035 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004036 enum yang_keyword kw;
4037 struct lysp_deviation *dev;
4038
Radek Krejci2c4e7172018-10-19 15:56:26 +02004039 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004040
4041 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004042 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
David Sedlákb9b892c2019-07-12 14:44:02 +02004043 YANG_CHECK_NONEMPTY(ctx, word_len, "deviation");
Radek Krejci44ceedc2018-10-02 15:54:31 +02004044 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004045
Radek Krejci6d6556c2018-11-08 09:37:45 +01004046 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004047 switch (kw) {
4048 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004049 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 +02004050 break;
4051 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004052 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004053 break;
4054 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004055 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 +02004056 break;
4057 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004058 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004059 break;
4060 default:
David Sedlákb3077192019-06-19 10:55:37 +02004061 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004062 return LY_EVALID;
4063 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004064 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004065 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004066checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004067 /* mandatory substatements */
4068 if (!dev->deviates) {
David Sedlákb3077192019-06-19 10:55:37 +02004069 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004070 return LY_EVALID;
4071 }
4072
4073 return ret;
4074}
4075
Michal Vaskoea5abea2018-09-18 13:10:54 +02004076/**
4077 * @brief Parse the feature statement.
4078 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004079 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004080 * @param[in,out] data Data to read from, always moved to currently handled character.
4081 * @param[in,out] features Features to add to.
4082 *
4083 * @return LY_ERR values.
4084 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004085LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004086parse_feature(struct lys_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004087{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004088 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004089 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004090 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004091 enum yang_keyword kw;
4092 struct lysp_feature *feat;
4093
Radek Krejci2c4e7172018-10-19 15:56:26 +02004094 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004095
4096 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004097 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004098 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004099
Radek Krejci6d6556c2018-11-08 09:37:45 +01004100 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004101 switch (kw) {
4102 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004103 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 +02004104 break;
4105 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004106 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 +02004107 break;
4108 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004109 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 +02004110 break;
4111 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004112 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004113 break;
4114 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004115 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004116 break;
4117 default:
David Sedlákb3077192019-06-19 10:55:37 +02004118 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004119 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004120 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004121 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004122 return ret;
4123}
4124
Michal Vaskoea5abea2018-09-18 13:10:54 +02004125/**
4126 * @brief Parse the identity statement.
4127 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004128 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004129 * @param[in,out] data Data to read from, always moved to currently handled character.
4130 * @param[in,out] identities Identities to add to.
4131 *
4132 * @return LY_ERR values.
4133 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004134LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004135parse_identity(struct lys_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004136{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004137 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004138 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004139 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004140 enum yang_keyword kw;
4141 struct lysp_ident *ident;
4142
Radek Krejci2c4e7172018-10-19 15:56:26 +02004143 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004144
4145 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004146 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004147 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004148
Radek Krejci6d6556c2018-11-08 09:37:45 +01004149 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004150 switch (kw) {
4151 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004152 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 +02004153 break;
4154 case YANG_IF_FEATURE:
Radek Krejciceaf2122019-01-02 15:03:26 +01004155 YANG_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004156 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 +02004157 break;
4158 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004159 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 +02004160 break;
4161 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004162 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004163 break;
4164 case YANG_BASE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004165 if (ident->bases && ctx->mod_version < 2) {
David Sedlákb3077192019-06-19 10:55:37 +02004166 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 +01004167 return LY_EVALID;
4168 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004169 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 +02004170 break;
4171 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004172 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004173 break;
4174 default:
David Sedlákb3077192019-06-19 10:55:37 +02004175 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004176 return LY_EVALID;
4177 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004178 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179 return ret;
4180}
4181
Michal Vaskoea5abea2018-09-18 13:10:54 +02004182/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004183 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004184 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004185 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004186 * @param[in,out] data Data to read from, always moved to currently handled character.
4187 * @param[in,out] mod Module to write to.
4188 *
4189 * @return LY_ERR values.
4190 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004191LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004192parse_module(struct lys_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004193{
4194 LY_ERR ret = 0;
4195 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004196 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004197 enum yang_keyword kw, prev_kw = 0;
4198 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004199 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004200
4201 /* (sub)module name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004202 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004203 INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004204
Radek Krejci6d6556c2018-11-08 09:37:45 +01004205 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004206
Radek Krejcie3846472018-10-15 15:24:51 +02004207#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004208 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 +02004209
Michal Vasko7fbc8162018-09-17 10:35:16 +02004210 switch (kw) {
4211 /* module header */
4212 case YANG_NAMESPACE:
4213 case YANG_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004214 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4215 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004216 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004217 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004218 break;
4219 /* linkage */
4220 case YANG_INCLUDE:
4221 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004222 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004223 break;
4224 /* meta */
4225 case YANG_ORGANIZATION:
4226 case YANG_CONTACT:
4227 case YANG_DESCRIPTION:
4228 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004229 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004230 break;
4231
4232 /* revision */
4233 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004234 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004235 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004236 /* body */
4237 case YANG_ANYDATA:
4238 case YANG_ANYXML:
4239 case YANG_AUGMENT:
4240 case YANG_CHOICE:
4241 case YANG_CONTAINER:
4242 case YANG_DEVIATION:
4243 case YANG_EXTENSION:
4244 case YANG_FEATURE:
4245 case YANG_GROUPING:
4246 case YANG_IDENTITY:
4247 case YANG_LEAF:
4248 case YANG_LEAF_LIST:
4249 case YANG_LIST:
4250 case YANG_NOTIFICATION:
4251 case YANG_RPC:
4252 case YANG_TYPEDEF:
4253 case YANG_USES:
4254 case YANG_CUSTOM:
4255 mod_stmt = Y_MOD_BODY;
4256 break;
4257 default:
4258 /* error handled in the next switch */
4259 break;
4260 }
Radek Krejcie3846472018-10-15 15:24:51 +02004261#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004262
Radek Krejcie3846472018-10-15 15:24:51 +02004263 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004264 switch (kw) {
4265 /* module header */
4266 case YANG_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004267 LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
4268 ctx->mod_version = mod->mod->version;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004269 break;
4270 case YANG_NAMESPACE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004271 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 +02004272 break;
4273 case YANG_PREFIX:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004274 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 +02004275 break;
4276
4277 /* linkage */
4278 case YANG_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004279 LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004280 break;
4281 case YANG_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004282 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004283 break;
4284
4285 /* meta */
4286 case YANG_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004287 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 +02004288 break;
4289 case YANG_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004290 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 +02004291 break;
4292 case YANG_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004293 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 +02004294 break;
4295 case YANG_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004296 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 +02004297 break;
4298
4299 /* revision */
4300 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004301 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004302 break;
4303
4304 /* body */
4305 case YANG_ANYDATA:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004306 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci10113652018-11-14 16:56:50 +01004307 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004308 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004309 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004310 break;
4311 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004312 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004313 break;
4314 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004315 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004316 break;
4317 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004318 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004319 break;
4320 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004321 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004322 break;
4323 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004324 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004325 break;
4326 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004327 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004328 break;
4329
4330 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004331 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004332 break;
4333 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004334 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004335 break;
4336 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004337 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004338 break;
4339 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004340 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004341 break;
4342 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004343 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004344 break;
4345 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004346 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004347 break;
4348 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004349 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004350 break;
4351 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004352 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004353 break;
4354 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004355 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004356 break;
4357 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004358 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004359 break;
4360
4361 default:
David Sedlákb3077192019-06-19 10:55:37 +02004362 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004363 return LY_EVALID;
4364 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004365 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004366 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004367
Radek Krejci6d6556c2018-11-08 09:37:45 +01004368checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004369 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02004370 LY_CHECK_RET(parse_finalize_reallocated(ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004371
Michal Vasko7fbc8162018-09-17 10:35:16 +02004372 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004373 if (!mod->mod->ns) {
David Sedlákb3077192019-06-19 10:55:37 +02004374 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004375 return LY_EVALID;
4376 } else if (!mod->mod->prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02004377 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004378 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004379 }
4380
Radek Krejcie9e987e2018-10-31 12:50:27 +01004381 /* submodules share the namespace with the module names, so there must not be
4382 * a submodule of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004383 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->mod->name, NULL);
4384 if (dup) {
David Sedlákb3077192019-06-19 10:55:37 +02004385 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 +01004386 return LY_EVALID;
4387 }
4388
4389 return ret;
4390}
4391
4392/**
4393 * @brief Parse submodule substatements.
4394 *
4395 * @param[in] ctx yang parser context for logging.
4396 * @param[in,out] data Data to read from, always moved to currently handled character.
4397 * @param[out] submod Parsed submodule structure.
4398 *
4399 * @return LY_ERR values.
4400 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004401LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004402parse_submodule(struct lys_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004403{
4404 LY_ERR ret = 0;
4405 char *buf, *word;
4406 size_t word_len;
4407 enum yang_keyword kw, prev_kw = 0;
4408 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4409 struct lysp_submodule *dup;
4410
4411 /* submodule name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004412 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004413 INSERT_WORD(ctx, buf, submod->name, word, word_len);
4414
4415 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
4416
4417#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004418 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 +01004419
4420 switch (kw) {
4421 /* module header */
4422 case YANG_BELONGS_TO:
4423 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4424 break;
4425 case YANG_YANG_VERSION:
4426 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4427 break;
4428 /* linkage */
4429 case YANG_INCLUDE:
4430 case YANG_IMPORT:
4431 CHECK_ORDER(Y_MOD_LINKAGE);
4432 break;
4433 /* meta */
4434 case YANG_ORGANIZATION:
4435 case YANG_CONTACT:
4436 case YANG_DESCRIPTION:
4437 case YANG_REFERENCE:
4438 CHECK_ORDER(Y_MOD_META);
4439 break;
4440
4441 /* revision */
4442 case YANG_REVISION:
4443 CHECK_ORDER(Y_MOD_REVISION);
4444 break;
4445 /* body */
4446 case YANG_ANYDATA:
4447 case YANG_ANYXML:
4448 case YANG_AUGMENT:
4449 case YANG_CHOICE:
4450 case YANG_CONTAINER:
4451 case YANG_DEVIATION:
4452 case YANG_EXTENSION:
4453 case YANG_FEATURE:
4454 case YANG_GROUPING:
4455 case YANG_IDENTITY:
4456 case YANG_LEAF:
4457 case YANG_LEAF_LIST:
4458 case YANG_LIST:
4459 case YANG_NOTIFICATION:
4460 case YANG_RPC:
4461 case YANG_TYPEDEF:
4462 case YANG_USES:
4463 case YANG_CUSTOM:
4464 mod_stmt = Y_MOD_BODY;
4465 break;
4466 default:
4467 /* error handled in the next switch */
4468 break;
4469 }
4470#undef CHECK_ORDER
4471
4472 prev_kw = kw;
4473 switch (kw) {
4474 /* module header */
4475 case YANG_YANG_VERSION:
4476 LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
4477 ctx->mod_version = submod->version;
4478 break;
4479 case YANG_BELONGS_TO:
4480 LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
4481 break;
4482
4483 /* linkage */
4484 case YANG_INCLUDE:
4485 LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
4486 break;
4487 case YANG_IMPORT:
4488 LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
4489 break;
4490
4491 /* meta */
4492 case YANG_ORGANIZATION:
4493 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
4494 break;
4495 case YANG_CONTACT:
4496 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
4497 break;
4498 case YANG_DESCRIPTION:
4499 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
4500 break;
4501 case YANG_REFERENCE:
4502 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
4503 break;
4504
4505 /* revision */
4506 case YANG_REVISION:
4507 LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
4508 break;
4509
4510 /* body */
4511 case YANG_ANYDATA:
4512 YANG_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
4513 /* fall through */
4514 case YANG_ANYXML:
4515 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
4516 break;
4517 case YANG_CHOICE:
4518 LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
4519 break;
4520 case YANG_CONTAINER:
4521 LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
4522 break;
4523 case YANG_LEAF:
4524 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
4525 break;
4526 case YANG_LEAF_LIST:
4527 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
4528 break;
4529 case YANG_LIST:
4530 LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
4531 break;
4532 case YANG_USES:
4533 LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
4534 break;
4535
4536 case YANG_AUGMENT:
4537 LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
4538 break;
4539 case YANG_DEVIATION:
4540 LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
4541 break;
4542 case YANG_EXTENSION:
4543 LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
4544 break;
4545 case YANG_FEATURE:
4546 LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
4547 break;
4548 case YANG_GROUPING:
4549 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
4550 break;
4551 case YANG_IDENTITY:
4552 LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
4553 break;
4554 case YANG_NOTIFICATION:
4555 LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
4556 break;
4557 case YANG_RPC:
4558 LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
4559 break;
4560 case YANG_TYPEDEF:
4561 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
4562 break;
4563 case YANG_CUSTOM:
4564 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
4565 break;
4566
4567 default:
David Sedlákb3077192019-06-19 10:55:37 +02004568 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004569 return LY_EVALID;
4570 }
4571 }
4572 LY_CHECK_RET(ret);
4573
4574checks:
4575 /* finalize parent pointers to the reallocated items */
Radek Krejci7fc68292019-06-12 13:51:09 +02004576 LY_CHECK_RET(parse_finalize_reallocated(ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004577
4578 /* mandatory substatements */
4579 if (!submod->belongsto) {
David Sedlákb3077192019-06-19 10:55:37 +02004580 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004581 return LY_EVALID;
4582 }
4583
4584 /* submodules share the namespace with the module names, so there must not be
4585 * a submodule of the same name in the context, no need for revision matching */
4586 dup = ly_ctx_get_submodule(ctx->ctx, NULL, submod->name, NULL);
4587 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
David Sedlákb3077192019-06-19 10:55:37 +02004588 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004589 return LY_EVALID;
4590 }
4591
Michal Vasko7fbc8162018-09-17 10:35:16 +02004592 return ret;
4593}
4594
Radek Krejcid4557c62018-09-17 11:42:09 +02004595LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004596yang_parse_submodule(struct lys_parser_ctx *context, const char *data, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004597{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004598 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004599 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004600 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004601 enum yang_keyword kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004602 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004603
4604 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004605 ret = get_keyword(context, &data, &kw, &word, &word_len);
4606 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004607
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004608 if (kw == YANG_MODULE) {
4609 LOGERR(context->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
4610 ret = LY_EINVAL;
4611 goto cleanup;
4612 } else if (kw != YANG_SUBMODULE) {
David Sedlákb3077192019-06-19 10:55:37 +02004613 LOGVAL_PARSER(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004614 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004615 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004616 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004617 }
4618
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004619 mod_p = calloc(1, sizeof *mod_p);
4620 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4621 mod_p->parsing = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004622
4623 /* substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004624 ret = parse_submodule(context, &data, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004625 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004626
4627 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004628 while(*data && isspace(*data)) {
4629 data++;
4630 }
4631 if (*data) {
David Sedlákb3077192019-06-19 10:55:37 +02004632 LOGVAL_PARSER(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004633 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004634 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004635 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004636 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004637
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004638 mod_p->parsing = 0;
4639 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004640
Radek Krejcibbe09a92018-11-08 09:36:54 +01004641cleanup:
4642 if (ret) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004643 lysp_submodule_free(context->ctx, mod_p);
4644 }
4645
4646 return ret;
4647}
4648
4649LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004650yang_parse_module(struct lys_parser_ctx *context, const char *data, struct lys_module *mod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004651{
4652 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004653 char *word;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004654 size_t word_len;
4655 enum yang_keyword kw;
4656 struct lysp_module *mod_p = NULL;
4657
4658 /* "module"/"submodule" */
4659 ret = get_keyword(context, &data, &kw, &word, &word_len);
4660 LY_CHECK_GOTO(ret, cleanup);
4661
4662 if (kw == YANG_SUBMODULE) {
4663 LOGERR(context->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
4664 ret = LY_EINVAL;
4665 goto cleanup;
4666 } else if (kw != YANG_MODULE) {
David Sedlákb3077192019-06-19 10:55:37 +02004667 LOGVAL_PARSER(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004668 ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004669 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004670 goto cleanup;
4671 }
4672
4673 mod_p = calloc(1, sizeof *mod_p);
4674 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
4675 mod_p->mod = mod;
4676 mod_p->parsing = 1;
4677
4678 /* substatements */
4679 ret = parse_module(context, &data, mod_p);
4680 LY_CHECK_GOTO(ret, cleanup);
4681
4682 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004683 while(*data && isspace(*data)) {
4684 data++;
4685 }
4686 if (*data) {
David Sedlákb3077192019-06-19 10:55:37 +02004687 LOGVAL_PARSER(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004688 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004689 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004690 goto cleanup;
4691 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004692
4693 mod_p->parsing = 0;
4694 mod->parsed = mod_p;
4695
4696cleanup:
4697 if (ret) {
4698 lysp_module_free(mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004699 }
4700
Michal Vasko7fbc8162018-09-17 10:35:16 +02004701 return ret;
4702}