blob: 57d42bdd71d38cf5475742ce5aee7b8314d01a1e [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"
Radek Krejcie7b95092019-05-15 11:03:07 +020027#include "log.h"
Radek Krejci0935f412019-08-20 16:15:18 +020028#include "plugins_exts.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020029#include "set.h"
30#include "tree.h"
31#include "tree_schema.h"
Radek Krejci70853c52018-10-15 14:46:16 +020032#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020033
Radek Krejciceaf2122019-01-02 15:03:26 +010034/**
35 * @brief 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)); \
Radek Krejcid6b76452019-09-03 17:03:03 +020068 if (KW == LY_STMT_SYNTAX_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 } \
Radek Krejcid6b76452019-09-03 17:03:03 +020072 if (KW != LY_STMT_SYNTAX_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); \
Radek Krejcid6b76452019-09-03 17:03:03 +020077 !ERR && (KW != LY_STMT_SYNTAX_RIGHT_BRACE); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020078 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
79
Radek Krejci2d7a47b2019-05-16 13:34:10 +020080LY_ERR parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
81LY_ERR parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
82LY_ERR parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
83LY_ERR parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
84LY_ERR parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
85LY_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 +020086
Michal Vaskoea5abea2018-09-18 13:10:54 +020087/**
88 * @brief Add another character to dynamic buffer, a low-level function.
89 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020090 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +020091 *
Radek Krejci404251e2018-10-09 12:06:44 +020092 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +020093 * @param[in, out] input Input string to process.
94 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +020095 * @param[in,out] buf Buffer to use, can be moved by realloc().
96 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +020097 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +020098 *
99 * @return LY_ERR values.
100 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200101LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200102buf_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 +0200103{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200104 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200105 *buf_len += 16;
106 *buf = ly_realloc(*buf, *buf_len);
107 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
108 }
Radek Krejcic0917392019-04-10 13:04:04 +0200109 if (*buf_used) {
110 memcpy(&(*buf)[*buf_used], *input, len);
111 } else {
112 memcpy(*buf, *input, len);
113 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200114
Radek Krejci44ceedc2018-10-02 15:54:31 +0200115 (*buf_used) += len;
116 (*input) += len;
117
Michal Vasko7fbc8162018-09-17 10:35:16 +0200118 return LY_SUCCESS;
119}
120
Michal Vaskoea5abea2018-09-18 13:10:54 +0200121/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200122 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
123 *
124 * @param[in] ctx yang parser context for logging.
125 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
126 * when function returns.
127 * @param[in] arg Type of the input string to select method of checking character validity.
128 * @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 +0200129 * 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 +0200130 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
131 * @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 +0200132 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200133 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
David Sedlák40bb13b2019-07-10 14:34:18 +0200134 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
135 * 0 - colon not yet found (no prefix)
136 * 1 - \p c is the colon character
137 * 2 - prefix already processed, now processing the identifier
Michal Vaskoea5abea2018-09-18 13:10:54 +0200138 *
139 * @return LY_ERR values.
140 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200141LY_ERR
David Sedlák40bb13b2019-07-10 14:34:18 +0200142buf_store_char(struct lys_parser_ctx *ctx, const char **input, enum yang_arg arg, char **word_p,
143 size_t *word_len, char **word_b, size_t *buf_len, int need_buf, int *prefix)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200144{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200145 unsigned int c;
146 size_t len;
147
Radek Krejcif29b7c32019-04-09 16:17:49 +0200148 /* check valid combination of input paremeters - if need_buf specified, word_b must be provided */
149 assert(!need_buf || (need_buf && word_b));
150
Radek Krejci44ceedc2018-10-02 15:54:31 +0200151 /* get UTF8 code point (and number of bytes coding the character) */
152 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
David Sedlákb3077192019-06-19 10:55:37 +0200153 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200154 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200155 if (c == '\n') {
156 ctx->indent = 0;
157 } else {
158 /* note - even the multibyte character is count as 1 */
159 ++ctx->indent;
160 }
161
Radek Krejci44ceedc2018-10-02 15:54:31 +0200162 /* check character validity */
163 switch (arg) {
164 case Y_IDENTIF_ARG:
David Sedlák4a650532019-07-10 11:55:18 +0200165 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, !(*word_len), NULL));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200166 break;
167 case Y_PREF_IDENTIF_ARG:
David Sedlák40bb13b2019-07-10 14:34:18 +0200168 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, !(*word_len), prefix));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200169 break;
170 case Y_STR_ARG:
171 case Y_MAYBE_STR_ARG:
David Sedlák4a650532019-07-10 11:55:18 +0200172 LY_CHECK_RET(lysp_check_stringchar(ctx, c));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200173 break;
174 }
175
Michal Vasko7fbc8162018-09-17 10:35:16 +0200176 if (word_b && *word_b) {
177 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200178 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200179 return LY_EMEM;
180 }
181
182 /* in case of realloc */
183 *word_p = *word_b;
Radek Krejcif29b7c32019-04-09 16:17:49 +0200184 } else if (word_b && need_buf) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200185 /* first time we need a buffer, copy everything read up to now */
186 if (*word_len) {
187 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200188 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200189 *buf_len = *word_len;
190 memcpy(*word_b, *word_p, *word_len);
191 }
192
193 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200194 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200195 return LY_EMEM;
196 }
197
198 /* in case of realloc */
199 *word_p = *word_b;
200 } else {
201 /* just remember the first character pointer */
202 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200203 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200204 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200205 /* ... and update the word's length */
206 (*word_len) += len;
207 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200208 }
209
210 return LY_SUCCESS;
211}
212
Michal Vaskoea5abea2018-09-18 13:10:54 +0200213/**
214 * @brief Skip YANG comment in data.
215 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200216 * @param[in] ctx yang parser context for logging.
217 * @param[in,out] data Data to read from, automatically moved after the comment.
218 * @param[in] comment Type of the comment to process:
219 * 1 for a one-line comment,
220 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200221 *
222 * @return LY_ERR values.
223 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200224LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200225skip_comment(struct lys_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200226{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200227 /* internal statuses: 0 - comment ended,
228 * 1 - in line comment,
229 * 2 - in block comment,
230 * 3 - in block comment with last read character '*'
231 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200232 while (**data && comment) {
233 switch (comment) {
234 case 1:
235 if (**data == '\n') {
236 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200237 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200238 }
239 break;
240 case 2:
241 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200242 comment = 3;
243 } else if (**data == '\n') {
244 ++ctx->line;
245 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200246 break;
247 case 3:
248 if (**data == '/') {
249 comment = 0;
Radek Krejci5b930492019-06-11 14:54:08 +0200250 } else if (**data != '*') {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200251 if (**data == '\n') {
252 ++ctx->line;
253 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200254 comment = 2;
255 }
256 break;
257 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200258 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200259 }
260
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200261 if (**data == '\n') {
262 ctx->indent = 0;
263 } else {
264 ++ctx->indent;
265 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200266 ++(*data);
267 }
268
269 if (!**data && (comment > 1)) {
David Sedlákb3077192019-06-19 10:55:37 +0200270 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Unexpected end-of-input, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200271 return LY_EVALID;
272 }
273
274 return LY_SUCCESS;
275}
276
Michal Vaskoea5abea2018-09-18 13:10:54 +0200277/**
278 * @brief Read a quoted string from data.
279 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200280 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200281 * @param[in,out] data Data to read from, always moved to currently handled character.
282 * @param[in] arg Type of YANG keyword argument expected.
283 * @param[out] word_p Pointer to the read quoted string.
284 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
285 * set to NULL. Otherwise equal to \p word_p.
286 * @param[out] word_len Length of the read quoted string.
287 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
288 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
289 * indenation in the final quoted string.
290 *
291 * @return LY_ERR values.
292 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200293static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200294read_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 +0200295 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200296{
297 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
298 * 4 - string finished, now skipping whitespaces looking for +,
299 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200300 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200301 const char *c;
David Sedlák40bb13b2019-07-10 14:34:18 +0200302 int prefix = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200303
304 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200305 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200306 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200307 } else {
308 assert(**data == '\'');
309 string = 1;
310 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200311 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200312
313 while (**data && string) {
314 switch (string) {
315 case 1:
316 switch (**data) {
317 case '\'':
318 /* string may be finished, but check for + */
319 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200320 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200321 break;
322 default:
323 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200324 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 +0200325 break;
326 }
327 break;
328 case 2:
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 case '\\':
336 /* special character following */
337 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200338 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200339 break;
340 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200341 if (current_indent < block_indent) {
342 ++current_indent;
343 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200344 } else {
345 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200346 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 +0200347 }
348 break;
349 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200350 if (current_indent < block_indent) {
351 assert(need_buf);
352 current_indent += 8;
353 ctx->indent += 8;
354 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
355 /* store leftover spaces from the tab */
356 c = " ";
David Sedlák40bb13b2019-07-10 14:34:18 +0200357 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 +0200358 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200359 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200360 } else {
361 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200362 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200363 /* additional characters for indentation - only 1 was count in buf_store_char */
364 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200365 }
366 break;
367 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200368 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200369 /* we will be removing the indents so we need our own buffer */
370 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200371
372 /* remove trailing tabs and spaces */
373 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
374 --(*word_len);
375 }
376
377 /* start indentation */
378 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200379 }
380
381 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200382 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 +0200383
384 /* maintain line number */
385 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200386
387 /* reset context indentation counter for possible string after this one */
388 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200389 break;
390 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200391 /* first non-whitespace character, stop eating indentation */
392 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200393
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));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200396 break;
397 }
398 break;
399 case 3:
400 /* string encoded characters */
401 switch (**data) {
402 case 'n':
403 c = "\n";
404 break;
405 case 't':
406 c = "\t";
407 break;
408 case '\"':
409 c = *data;
410 break;
411 case '\\':
412 c = *data;
413 break;
414 default:
David Sedlákb3077192019-06-19 10:55:37 +0200415 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200416 return LY_EVALID;
417 }
418
419 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200420 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 +0200421
422 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200423 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200424 break;
425 case 4:
426 switch (**data) {
427 case '+':
428 /* string continues */
429 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200430 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200431 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200432 case '\n':
433 ++ctx->line;
434 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200435 case ' ':
436 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200437 /* just skip */
438 break;
439 default:
440 /* string is finished */
441 goto string_end;
442 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200443 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200444 break;
445 case 5:
446 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200447 case '\n':
448 ++ctx->line;
449 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200450 case ' ':
451 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200452 /* skip */
453 break;
454 case '\'':
455 string = 1;
456 break;
457 case '\"':
458 string = 2;
459 break;
460 default:
461 /* it must be quoted again */
David Sedlákb3077192019-06-19 10:55:37 +0200462 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200463 return LY_EVALID;
464 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200465 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200466 break;
467 default:
468 return LY_EINT;
469 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200470 }
471
472string_end:
Radek Krejci4e199f52019-05-28 09:09:28 +0200473 if (arg <= Y_PREF_IDENTIF_ARG && !(*word_len)) {
474 /* empty identifier */
David Sedlákb3077192019-06-19 10:55:37 +0200475 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Statement argument is required.");
Radek Krejci4e199f52019-05-28 09:09:28 +0200476 return LY_EVALID;
477 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200478 return LY_SUCCESS;
479}
480
Michal Vaskoea5abea2018-09-18 13:10:54 +0200481/**
482 * @brief Get another YANG string from the raw data.
483 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200484 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200485 * @param[in,out] data Data to read from, always moved to currently handled character.
486 * @param[in] arg Type of YANG keyword argument expected.
Radek Krejcid3ca0632019-04-16 16:54:54 +0200487 * @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 +0200488 * @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 +0200489 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
490 * set to NULL. Otherwise equal to \p word_p.
491 * @param[out] word_len Length of the read string.
492 *
493 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200494 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200495LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200496get_argument(struct lys_parser_ctx *ctx, const char **data, enum yang_arg arg,
Radek Krejcid3ca0632019-04-16 16:54:54 +0200497 uint16_t *flags, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200498{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200499 size_t buf_len = 0;
David Sedlák40bb13b2019-07-10 14:34:18 +0200500 int prefix = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200501 /* word buffer - dynamically allocated */
502 *word_b = NULL;
503
504 /* word pointer - just a pointer to data */
505 *word_p = NULL;
506
507 *word_len = 0;
508 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200509 switch (**data) {
510 case '\'':
511 case '\"':
512 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200513 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
David Sedlákb3077192019-06-19 10:55:37 +0200514 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data,
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200515 "unquoted string character, optsep, semicolon or opening brace");
516 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200517 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200518 if (flags) {
519 (*flags) |= (**data) == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
520 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100521 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200522 goto str_end;
523 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200524 if ((*data)[1] == '/') {
525 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200526 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100527 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200528 } else if ((*data)[1] == '*') {
529 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200530 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100531 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200532 } else {
533 /* not a comment after all */
David Sedlák40bb13b2019-07-10 14:34:18 +0200534 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 +0200535 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200536 break;
537 case ' ':
538 if (*word_len) {
539 /* word is finished */
540 goto str_end;
541 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200542 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200543 break;
544 case '\t':
545 if (*word_len) {
546 /* word is finished */
547 goto str_end;
548 }
549 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200550 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200551
552 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200553 break;
554 case '\n':
555 if (*word_len) {
556 /* word is finished */
557 goto str_end;
558 }
559 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200560 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200561
562 /* track line numbers */
563 ++ctx->line;
564
565 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200566 break;
567 case ';':
568 case '{':
569 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
570 /* word is finished */
571 goto str_end;
572 }
573
David Sedlákb3077192019-06-19 10:55:37 +0200574 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200575 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200576 case '}':
577 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
David Sedlákb3077192019-06-19 10:55:37 +0200578 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data,
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200579 "unquoted string character, optsep, semicolon or opening brace");
580 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200581 default:
David Sedlák40bb13b2019-07-10 14:34:18 +0200582 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 +0200583 break;
584 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200585 }
586
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200587 /* unexpected end of loop */
David Sedlákb3077192019-06-19 10:55:37 +0200588 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200589 return LY_EVALID;
590
Michal Vasko7fbc8162018-09-17 10:35:16 +0200591str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200592 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200593 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200594 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
595 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
596 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200597 *word_p = *word_b;
598 }
599
600 return LY_SUCCESS;
601}
602
Michal Vaskoea5abea2018-09-18 13:10:54 +0200603/**
604 * @brief Get another YANG keyword from the raw data.
605 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200606 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200607 * @param[in,out] data Data to read from, always moved to currently handled character.
608 * @param[out] kw YANG keyword read.
609 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
610 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
611 *
612 * @return LY_ERR values.
613 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200614LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200615get_keyword(struct lys_parser_ctx *ctx, const char **data, enum ly_stmt *kw, char **word_p, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200616{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200617 int prefix;
618 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200619 unsigned int c;
620 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200621
622 if (word_p) {
623 *word_p = NULL;
624 *word_len = 0;
625 }
626
627 /* first skip "optsep", comments */
628 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200629 switch (**data) {
630 case '/':
631 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200632 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200633 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100634 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200635 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200636 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200637 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100638 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200639 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200640 /* error - not a comment after all, keyword cannot start with slash */
David Sedlákb3077192019-06-19 10:55:37 +0200641 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
Radek Krejcidcc7b322018-10-11 14:24:02 +0200642 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200643 }
Radek Krejci13028282019-06-11 14:56:48 +0200644 continue;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200645 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200646 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200647 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200648 ctx->indent = 0;
649 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200650 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200651 /* skip whitespaces (optsep) */
652 ++ctx->indent;
653 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200654 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200655 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200656 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200657 break;
658 default:
659 /* either a keyword start or an invalid character */
660 goto keyword_start;
661 }
662
663 ++(*data);
664 }
665
666keyword_start:
667 word_start = *data;
David Sedlák5f8f0332019-06-18 16:34:30 +0200668 *kw = lysp_match_kw(ctx, data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200669
Radek Krejcid6b76452019-09-03 17:03:03 +0200670 if (*kw == LY_STMT_SYNTAX_SEMICOLON || *kw == LY_STMT_SYNTAX_LEFT_BRACE || *kw == LY_STMT_SYNTAX_RIGHT_BRACE) {
Radek Krejci626df482018-10-11 15:06:31 +0200671 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200672 }
673
Radek Krejcid6b76452019-09-03 17:03:03 +0200674 if (*kw != LY_STMT_NONE) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200675 /* make sure we have the whole keyword */
676 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200677 case '\n':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200678 case '\t':
Radek Krejciabdd8062019-06-11 16:44:19 +0200679 case ' ':
680 /* mandatory "sep" is just checked, not eaten so nothing in the context is updated */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200681 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200682 case ':':
683 /* keyword is not actually a keyword, but prefix of an extension.
684 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
685 * and we will be checking the keyword (extension instance) itself */
686 prefix = 1;
687 MOVE_INPUT(ctx, data, 1);
688 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200689 case '{':
690 /* allowed only for input and output statements which can be without arguments */
Radek Krejcid6b76452019-09-03 17:03:03 +0200691 if (*kw == LY_STMT_INPUT || *kw == LY_STMT_OUTPUT) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200692 break;
693 }
694 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200695 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200696 MOVE_INPUT(ctx, data, 1);
David Sedlákb3077192019-06-19 10:55:37 +0200697 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
Radek Krejci44ceedc2018-10-02 15:54:31 +0200698 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200699 return LY_EVALID;
700 }
701 } else {
702 /* still can be an extension */
703 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200704extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200705 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200706 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
David Sedlákb3077192019-06-19 10:55:37 +0200707 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200708 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200709 /* check character validity */
David Sedlák4a650532019-07-10 11:55:18 +0200710 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200711 }
712 if (!**data) {
David Sedlákb3077192019-06-19 10:55:37 +0200713 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200714 return LY_EVALID;
715 }
716
717 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200718 if (prefix != 2) {
David Sedlákb3077192019-06-19 10:55:37 +0200719 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200720 return LY_EVALID;
721 }
722
Radek Krejcid6b76452019-09-03 17:03:03 +0200723 *kw = LY_STMT_EXTENSION_INSTANCE;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200724 }
Radek Krejci626df482018-10-11 15:06:31 +0200725success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200726 if (word_p) {
727 *word_p = (char *)word_start;
728 *word_len = *data - word_start;
729 }
730
731 return LY_SUCCESS;
732}
733
Michal Vaskoea5abea2018-09-18 13:10:54 +0200734/**
735 * @brief Parse extension instance substatements.
736 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200737 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200738 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci335332a2019-09-05 13:03:35 +0200739 * @param[in] kw Statement keyword value matching @p word value.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200740 * @param[in] word Extension instance substatement name (keyword).
741 * @param[in] word_len Extension instance substatement name length.
742 * @param[in,out] child Children of this extension instance to add to.
743 *
744 * @return LY_ERR values.
745 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200746static LY_ERR
Radek Krejci335332a2019-09-05 13:03:35 +0200747parse_ext_substmt(struct lys_parser_ctx *ctx, const char **data, enum ly_stmt kw, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200748 struct lysp_stmt **child)
749{
750 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100751 LY_ERR ret = LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200752 enum ly_stmt child_kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200753 struct lysp_stmt *stmt, *par_child;
754
755 stmt = calloc(1, sizeof *stmt);
756 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
757
Radek Krejcibb9b1982019-04-08 14:24:59 +0200758 /* insert into parent statements */
759 if (!*child) {
760 *child = stmt;
761 } else {
762 for (par_child = *child; par_child->next; par_child = par_child->next);
763 par_child->next = stmt;
764 }
765
Radek Krejci44ceedc2018-10-02 15:54:31 +0200766 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci335332a2019-09-05 13:03:35 +0200767 stmt->kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200768
769 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200770 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200771
Radek Krejci0ae092d2018-09-20 16:43:19 +0200772 if (word) {
773 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200774 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200775 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200776 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200777 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200778 }
779
Radek Krejci335332a2019-09-05 13:03:35 +0200780 YANG_READ_SUBSTMT_FOR(ctx, data, child_kw, word, word_len, ret, ) {
781 LY_CHECK_RET(parse_ext_substmt(ctx, data, child_kw, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200782 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200783 return ret;
784}
785
Michal Vaskoea5abea2018-09-18 13:10:54 +0200786/**
787 * @brief Parse extension instance.
788 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200789 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200790 * @param[in,out] data Data to read from, always moved to currently handled character.
791 * @param[in] ext_name Extension instance substatement name (keyword).
792 * @param[in] ext_name_len Extension instance substatement name length.
793 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
794 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
795 * @param[in,out] exts Extension instances to add to.
796 *
797 * @return LY_ERR values.
798 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200799static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200800parse_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 +0200801 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
802{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100803 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200804 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200805 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200806 struct lysp_ext_instance *e;
Radek Krejcid6b76452019-09-03 17:03:03 +0200807 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200808
Radek Krejci2c4e7172018-10-19 15:56:26 +0200809 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200810
811 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200812 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200813 e->insubstmt = insubstmt;
814 e->insubstmt_index = insubstmt_index;
815
816 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200817 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200818
Radek Krejci0ae092d2018-09-20 16:43:19 +0200819 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200820 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200821 }
822
Radek Krejci6d6556c2018-11-08 09:37:45 +0100823 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci335332a2019-09-05 13:03:35 +0200824 LY_CHECK_RET(parse_ext_substmt(ctx, data, kw, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200825 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200826 return ret;
827}
828
Michal Vaskoea5abea2018-09-18 13:10:54 +0200829/**
830 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
831 * description, etc...
832 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200833 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200834 * @param[in,out] data Data to read from, always moved to currently handled character.
835 * @param[in] substmt Type of this substatement.
836 * @param[in] substmt_index Index of this substatement.
837 * @param[in,out] value Place to store the parsed value.
838 * @param[in] arg Type of the YANG keyword argument (of the value).
839 * @param[in,out] exts Extension instances to add to.
840 *
841 * @return LY_ERR values.
842 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200843static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200844parse_text_field(struct lys_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200845 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
846{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100847 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200848 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200849 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200850 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200851
852 if (*value) {
David Sedlákb3077192019-06-19 10:55:37 +0200853 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200854 return LY_EVALID;
855 }
856
857 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200858 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200859
860 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200861 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200862
Radek Krejci6d6556c2018-11-08 09:37:45 +0100863 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200864 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200865 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100866 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200867 break;
868 default:
David Sedlákb3077192019-06-19 10:55:37 +0200869 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200870 return LY_EVALID;
871 }
872 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200873 return ret;
874}
875
Michal Vaskoea5abea2018-09-18 13:10:54 +0200876/**
877 * @brief Parse the yang-version statement.
878 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200879 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200880 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100881 * @param[out] version Storage for the parsed information.
882 * @param[in, out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200883 *
884 * @return LY_ERR values.
885 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200886static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200887parse_yangversion(struct lys_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200888{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100889 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200890 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200891 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200892 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200893
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100894 if (*version) {
David Sedlákb3077192019-06-19 10:55:37 +0200895 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200896 return LY_EVALID;
897 }
898
899 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200900 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200901
902 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100903 *version = LYS_VERSION_1_0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200904 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100905 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200906 } else {
David Sedlákb3077192019-06-19 10:55:37 +0200907 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200908 free(buf);
909 return LY_EVALID;
910 }
911 free(buf);
912
Radek Krejci6d6556c2018-11-08 09:37:45 +0100913 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200914 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200915 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100916 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200917 break;
918 default:
David Sedlákb3077192019-06-19 10:55:37 +0200919 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200920 return LY_EVALID;
921 }
922 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200923 return ret;
924}
925
Michal Vaskoea5abea2018-09-18 13:10:54 +0200926/**
927 * @brief Parse the belongs-to statement.
928 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200929 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200930 * @param[in,out] data Data to read from, always moved to currently handled character.
931 * @param[in,out] belongsto Place to store the parsed value.
932 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
933 * @param[in,out] exts Extension instances to add to.
934 *
935 * @return LY_ERR values.
936 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200937static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200938parse_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 +0200939{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100940 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200941 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200942 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200943 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200944
945 if (*belongsto) {
David Sedlákb3077192019-06-19 10:55:37 +0200946 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200947 return LY_EVALID;
948 }
949
950 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200951 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200952
Radek Krejci44ceedc2018-10-02 15:54:31 +0200953 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejcif09e4e82019-06-14 15:08:11 +0200954
Radek Krejci6d6556c2018-11-08 09:37:45 +0100955 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200956 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200957 case LY_STMT_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100958 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200959 break;
Radek Krejcid6b76452019-09-03 17:03:03 +0200960 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100961 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200962 break;
963 default:
David Sedlákb3077192019-06-19 10:55:37 +0200964 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200965 return LY_EVALID;
966 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200967 }
Radek Krejcic59bc972018-09-17 16:13:06 +0200968 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +0100969checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200970 /* mandatory substatements */
971 if (!*prefix) {
David Sedlákb3077192019-06-19 10:55:37 +0200972 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200973 return LY_EVALID;
974 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200975 return ret;
976}
977
Michal Vaskoea5abea2018-09-18 13:10:54 +0200978/**
979 * @brief Parse the revision-date statement.
980 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200981 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200982 * @param[in,out] data Data to read from, always moved to currently handled character.
983 * @param[in,out] rev Array to store the parsed value in.
984 * @param[in,out] exts Extension instances to add to.
985 *
986 * @return LY_ERR values.
987 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200988static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200989parse_revisiondate(struct lys_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200990{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100991 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200992 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200993 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200994 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200995
996 if (rev[0]) {
David Sedlákb3077192019-06-19 10:55:37 +0200997 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200998 return LY_EVALID;
999 }
1000
1001 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001002 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001003
1004 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001005 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001006 free(buf);
1007 return LY_EVALID;
1008 }
1009
1010 /* store value and spend buf if allocated */
1011 strncpy(rev, word, word_len);
1012 free(buf);
1013
Radek Krejci6d6556c2018-11-08 09:37:45 +01001014 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001015 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001016 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001017 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001018 break;
1019 default:
David Sedlákb3077192019-06-19 10:55:37 +02001020 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001021 return LY_EVALID;
1022 }
1023 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001024 return ret;
1025}
1026
Michal Vaskoea5abea2018-09-18 13:10:54 +02001027/**
1028 * @brief Parse the include statement.
1029 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001030 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001031 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001032 * @param[in,out] data Data to read from, always moved to currently handled character.
1033 * @param[in,out] includes Parsed includes to add to.
1034 *
1035 * @return LY_ERR values.
1036 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001037static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001038parse_include(struct lys_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001039{
Radek Krejcid33273d2018-10-25 14:55:52 +02001040 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001041 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001042 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001043 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001044 struct lysp_include *inc;
1045
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001046 LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001047
1048 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001049 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001050
Radek Krejci086c7132018-10-26 15:29:04 +02001051 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1052
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001053 /* submodules share the namespace with the module names, so there must not be
1054 * a module of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001055 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
David Sedlákb3077192019-06-19 10:55:37 +02001056 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001057 return LY_EVALID;
1058 }
1059
Radek Krejci6d6556c2018-11-08 09:37:45 +01001060 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001061 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001062 case LY_STMT_DESCRIPTION:
Radek Krejci335332a2019-09-05 13:03:35 +02001063 PARSER_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001064 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 +02001065 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001066 case LY_STMT_REFERENCE:
Radek Krejci335332a2019-09-05 13:03:35 +02001067 PARSER_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001068 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 +02001069 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001070 case LY_STMT_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001071 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001072 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001073 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001074 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001075 break;
1076 default:
David Sedlákb3077192019-06-19 10:55:37 +02001077 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001078 return LY_EVALID;
1079 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001080 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001081 return ret;
1082}
1083
Michal Vaskoea5abea2018-09-18 13:10:54 +02001084/**
1085 * @brief Parse the import statement.
1086 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001087 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001088 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001089 * @param[in,out] data Data to read from, always moved to currently handled character.
1090 * @param[in,out] imports Parsed imports to add to.
1091 *
1092 * @return LY_ERR values.
1093 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001094static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001095parse_import(struct lys_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001096{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001097 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001098 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001099 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001100 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001101 struct lysp_import *imp;
1102
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001103 LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001104
1105 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001106 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001107 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001108
Radek Krejci6d6556c2018-11-08 09:37:45 +01001109 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001110 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001111 case LY_STMT_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001112 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 +01001113 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001114 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001115 case LY_STMT_DESCRIPTION:
Radek Krejci335332a2019-09-05 13:03:35 +02001116 PARSER_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001117 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 +02001118 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001119 case LY_STMT_REFERENCE:
Radek Krejci335332a2019-09-05 13:03:35 +02001120 PARSER_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001121 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 +02001122 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001123 case LY_STMT_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001124 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001125 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001126 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001127 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001128 break;
1129 default:
David Sedlákb3077192019-06-19 10:55:37 +02001130 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001131 return LY_EVALID;
1132 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001133 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001134 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001135checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001136 /* mandatory substatements */
David Sedlákb3077192019-06-19 10:55:37 +02001137 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001138
1139 return ret;
1140}
1141
Michal Vaskoea5abea2018-09-18 13:10:54 +02001142/**
1143 * @brief Parse the revision statement.
1144 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001145 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001146 * @param[in,out] data Data to read from, always moved to currently handled character.
1147 * @param[in,out] revs Parsed revisions to add to.
1148 *
1149 * @return LY_ERR values.
1150 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001151static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001152parse_revision(struct lys_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001153{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001154 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001155 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001156 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001157 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001158 struct lysp_revision *rev;
1159
Radek Krejci2c4e7172018-10-19 15:56:26 +02001160 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001161
1162 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001163 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001164
1165 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001166 if (lysp_check_date(ctx, word, word_len, "revision")) {
David Sedlák68ef3dc2019-07-22 13:40:19 +02001167 free(buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001168 return LY_EVALID;
1169 }
1170
Radek Krejcib7db73a2018-10-24 14:18:40 +02001171 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001172 free(buf);
1173
Radek Krejci6d6556c2018-11-08 09:37:45 +01001174 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001175 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001176 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001177 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 +02001178 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001179 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001180 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 +02001181 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001182 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001183 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184 break;
1185 default:
David Sedlákb3077192019-06-19 10:55:37 +02001186 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001187 return LY_EVALID;
1188 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001190 return ret;
1191}
1192
Michal Vaskoea5abea2018-09-18 13:10:54 +02001193/**
1194 * @brief Parse a generic text field that can have more instances such as base.
1195 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001196 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001197 * @param[in,out] data Data to read from, always moved to currently handled character.
1198 * @param[in] substmt Type of this substatement.
1199 * @param[in,out] texts Parsed values to add to.
1200 * @param[in] arg Type of the expected argument.
1201 * @param[in,out] exts Extension instances to add to.
1202 *
1203 * @return LY_ERR values.
1204 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001205static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001206parse_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 +02001207 struct lysp_ext_instance **exts)
1208{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001209 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001210 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001211 const char **item;
1212 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001213 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001214
1215 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001216 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001217
1218 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001219 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001220
Radek Krejci151a5b72018-10-19 14:21:44 +02001221 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001222 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001223 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001224 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001225 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001226 break;
1227 default:
David Sedlákb3077192019-06-19 10:55:37 +02001228 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001229 return LY_EVALID;
1230 }
1231 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001232 return ret;
1233}
1234
Michal Vaskoea5abea2018-09-18 13:10:54 +02001235/**
1236 * @brief Parse the config statement.
1237 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001238 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001239 * @param[in,out] data Data to read from, always moved to currently handled character.
1240 * @param[in,out] flags Flags to add to.
1241 * @param[in,out] exts Extension instances to add to.
1242 *
1243 * @return LY_ERR values.
1244 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001245static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001246parse_config(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001247{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001248 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001249 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001250 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001251 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001252
1253 if (*flags & LYS_CONFIG_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001254 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001255 return LY_EVALID;
1256 }
1257
1258 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001259 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001260
1261 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1262 *flags |= LYS_CONFIG_W;
1263 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1264 *flags |= LYS_CONFIG_R;
1265 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001266 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001267 free(buf);
1268 return LY_EVALID;
1269 }
1270 free(buf);
1271
Radek Krejci6d6556c2018-11-08 09:37:45 +01001272 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001273 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001274 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001275 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001276 break;
1277 default:
David Sedlákb3077192019-06-19 10:55:37 +02001278 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001279 return LY_EVALID;
1280 }
1281 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001282 return ret;
1283}
1284
Michal Vaskoea5abea2018-09-18 13:10:54 +02001285/**
1286 * @brief Parse the mandatory statement.
1287 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001288 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001289 * @param[in,out] data Data to read from, always moved to currently handled character.
1290 * @param[in,out] flags Flags to add to.
1291 * @param[in,out] exts Extension instances to add to.
1292 *
1293 * @return LY_ERR values.
1294 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001295static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001296parse_mandatory(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001297{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001298 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001299 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001300 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001301 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001302
1303 if (*flags & LYS_MAND_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001304 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001305 return LY_EVALID;
1306 }
1307
1308 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001309 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001310
1311 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1312 *flags |= LYS_MAND_TRUE;
1313 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1314 *flags |= LYS_MAND_FALSE;
1315 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001316 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001317 free(buf);
1318 return LY_EVALID;
1319 }
1320 free(buf);
1321
Radek Krejci6d6556c2018-11-08 09:37:45 +01001322 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001323 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001324 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001325 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001326 break;
1327 default:
David Sedlákb3077192019-06-19 10:55:37 +02001328 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001329 return LY_EVALID;
1330 }
1331 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001332 return ret;
1333}
1334
Michal Vaskoea5abea2018-09-18 13:10:54 +02001335/**
1336 * @brief Parse a restriction such as range or length.
1337 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001338 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001339 * @param[in,out] data Data to read from, always moved to currently handled character.
1340 * @param[in] restr_kw Type of this particular restriction.
1341 * @param[in,out] exts Extension instances to add to.
1342 *
1343 * @return LY_ERR values.
1344 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001345static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02001346parse_restr(struct lys_parser_ctx *ctx, const char **data, enum ly_stmt restr_kw, struct lysp_restr *restr)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001347{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001348 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001349 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001350 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001351 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001352
1353 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001354 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001355
David Sedlákb9b892c2019-07-12 14:44:02 +02001356 YANG_CHECK_NONEMPTY(ctx, word_len, ly_stmt2str(restr_kw));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001357 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001358 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001359 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001360 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001361 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 +02001362 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001363 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001364 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 +02001365 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001366 case LY_STMT_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001367 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 +02001368 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001369 case LY_STMT_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001370 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 +02001371 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001372 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001373 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001374 break;
1375 default:
David Sedlákb3077192019-06-19 10:55:37 +02001376 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001377 return LY_EVALID;
1378 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001379 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001380 return ret;
1381}
1382
Michal Vaskoea5abea2018-09-18 13:10:54 +02001383/**
1384 * @brief Parse a restriction that can have more instances such as must.
1385 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001386 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001387 * @param[in,out] data Data to read from, always moved to currently handled character.
1388 * @param[in] restr_kw Type of this particular restriction.
1389 * @param[in,out] restrs Restrictions to add to.
1390 *
1391 * @return LY_ERR values.
1392 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001393static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02001394parse_restrs(struct lys_parser_ctx *ctx, const char **data, enum ly_stmt restr_kw, struct lysp_restr **restrs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001395{
1396 struct lysp_restr *restr;
1397
Radek Krejci2c4e7172018-10-19 15:56:26 +02001398 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001399 return parse_restr(ctx, data, restr_kw, restr);
1400}
1401
Michal Vaskoea5abea2018-09-18 13:10:54 +02001402/**
1403 * @brief Parse the status statement.
1404 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001405 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001406 * @param[in,out] data Data to read from, always moved to currently handled character.
1407 * @param[in,out] flags Flags to add to.
1408 * @param[in,out] exts Extension instances to add to.
1409 *
1410 * @return LY_ERR values.
1411 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001412static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001413parse_status(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001414{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001415 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001416 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001417 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001418 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001419
1420 if (*flags & LYS_STATUS_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001421 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001422 return LY_EVALID;
1423 }
1424
1425 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001426 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001427
1428 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1429 *flags |= LYS_STATUS_CURR;
1430 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1431 *flags |= LYS_STATUS_DEPRC;
1432 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1433 *flags |= LYS_STATUS_OBSLT;
1434 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001435 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001436 free(buf);
1437 return LY_EVALID;
1438 }
1439 free(buf);
1440
Radek Krejci6d6556c2018-11-08 09:37:45 +01001441 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001442 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001443 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001444 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001445 break;
1446 default:
David Sedlákb3077192019-06-19 10:55:37 +02001447 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001448 return LY_EVALID;
1449 }
1450 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001451 return ret;
1452}
1453
Michal Vaskoea5abea2018-09-18 13:10:54 +02001454/**
1455 * @brief Parse the when statement.
1456 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001457 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001458 * @param[in,out] data Data to read from, always moved to currently handled character.
1459 * @param[in,out] when_p When pointer to parse to.
1460 *
1461 * @return LY_ERR values.
1462 */
Radek Krejcif09e4e82019-06-14 15:08:11 +02001463LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001464parse_when(struct lys_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001465{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001466 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001467 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001468 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001469 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001470 struct lysp_when *when;
1471
1472 if (*when_p) {
David Sedlákb3077192019-06-19 10:55:37 +02001473 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001474 return LY_EVALID;
1475 }
1476
1477 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001478 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001479
1480 /* get value */
Radek Krejci2f54df52019-06-21 10:59:19 +02001481 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 +02001482 YANG_CHECK_NONEMPTY(ctx, word_len, "when");
Radek Krejci44ceedc2018-10-02 15:54:31 +02001483 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001484
Radek Krejcif09e4e82019-06-14 15:08:11 +02001485 *when_p = when;
1486
Radek Krejci6d6556c2018-11-08 09:37:45 +01001487 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001488 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001489 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001490 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 +02001491 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001492 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001493 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 +02001494 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001495 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001496 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001497 break;
1498 default:
David Sedlákb3077192019-06-19 10:55:37 +02001499 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001500 return LY_EVALID;
1501 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001502 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001503 return ret;
1504}
1505
Michal Vaskoea5abea2018-09-18 13:10:54 +02001506/**
1507 * @brief Parse the anydata or anyxml statement.
1508 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001509 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001510 * @param[in,out] data Data to read from, always moved to currently handled character.
1511 * @param[in] kw Type of this particular keyword.
1512 * @param[in,out] siblings Siblings to add to.
1513 *
1514 * @return LY_ERR values.
1515 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02001516LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02001517parse_any(struct lys_parser_ctx *ctx, const char **data, enum ly_stmt kw, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001518{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001519 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001520 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001521 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001522 struct lysp_node_anydata *any;
1523
David Sedlák60adc092019-08-06 15:57:02 +02001524 /* create new structure and insert into siblings */
1525 LY_LIST_NEW_RET(ctx->ctx, siblings, any, next);
1526
Radek Krejcid6b76452019-09-03 17:03:03 +02001527 any->nodetype = kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001528 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001529
Michal Vasko7fbc8162018-09-17 10:35:16 +02001530 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001531 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001532 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001533
1534 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001535 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001536 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001537 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001538 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001539 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001540 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001541 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 +02001542 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001543 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001544 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 +02001545 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001546 case LY_STMT_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001547 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001548 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001549 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001550 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001551 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001552 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001553 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 +02001554 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001555 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001556 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001557 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001558 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001559 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001560 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001561 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001562 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001563 break;
1564 default:
David Sedlákb3077192019-06-19 10:55:37 +02001565 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcid6b76452019-09-03 17:03:03 +02001566 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(LY_STMT_ANYDATA) : ly_stmt2str(LY_STMT_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001567 return LY_EVALID;
1568 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001569 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001570 return ret;
1571}
1572
Michal Vaskoea5abea2018-09-18 13:10:54 +02001573/**
1574 * @brief Parse the value or position statement. Substatement of type enum statement.
1575 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001576 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001577 * @param[in,out] data Data to read from, always moved to currently handled character.
1578 * @param[in] val_kw Type of this particular keyword.
1579 * @param[in,out] value Value to write to.
1580 * @param[in,out] flags Flags to write to.
1581 * @param[in,out] exts Extension instances to add to.
1582 *
1583 * @return LY_ERR values.
1584 */
David Sedlákd6ce6d72019-07-16 17:30:18 +02001585LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02001586parse_type_enum_value_pos(struct lys_parser_ctx *ctx, const char **data, enum ly_stmt val_kw, int64_t *value, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001587 struct lysp_ext_instance **exts)
1588{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001589 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001590 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001591 size_t word_len;
Radek Krejci4ad42aa2019-07-23 16:55:58 +02001592 long int num = 0;
1593 unsigned long int unum = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001594 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001595
1596 if (*flags & LYS_SET_VALUE) {
David Sedlákb3077192019-06-19 10:55:37 +02001597 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001598 return LY_EVALID;
1599 }
1600 *flags |= LYS_SET_VALUE;
1601
1602 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001603 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001604
Radek Krejcid6b76452019-09-03 17:03:03 +02001605 if (!word_len || (word[0] == '+') || ((word[0] == '0') && (word_len > 1)) || ((val_kw == LY_STMT_POSITION) && !strncmp(word, "-0", 2))) {
David Sedlákb3077192019-06-19 10:55:37 +02001606 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001607 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001608 }
1609
1610 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001611 if (val_kw == LY_STMT_VALUE) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001612 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001613 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlákb3077192019-06-19 10:55:37 +02001614 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001615 goto error;
1616 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001617 } else {
1618 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001619 if (unum > UINT64_C(4294967295)) {
David Sedlákb3077192019-06-19 10:55:37 +02001620 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001621 goto error;
1622 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001623 }
1624 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001625 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001626 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001627 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001628 }
1629 if (errno == ERANGE) {
David Sedlákb3077192019-06-19 10:55:37 +02001630 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001631 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001632 }
Radek Krejcid6b76452019-09-03 17:03:03 +02001633 if (val_kw == LY_STMT_VALUE) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001634 *value = num;
1635 } else {
1636 *value = unum;
1637 }
1638 free(buf);
1639
Radek Krejci6d6556c2018-11-08 09:37:45 +01001640 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001641 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001642 case LY_STMT_EXTENSION_INSTANCE:
1643 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, val_kw == LY_STMT_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001644 break;
1645 default:
David Sedlákb3077192019-06-19 10:55:37 +02001646 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001647 return LY_EVALID;
1648 }
1649 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001650 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001651
1652error:
1653 free(buf);
1654 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001655}
1656
Michal Vaskoea5abea2018-09-18 13:10:54 +02001657/**
1658 * @brief Parse the enum or bit statement. Substatement of type statement.
1659 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001660 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001661 * @param[in,out] data Data to read from, always moved to currently handled character.
1662 * @param[in] enum_kw Type of this particular keyword.
1663 * @param[in,out] enums Enums or bits to add to.
1664 *
1665 * @return LY_ERR values.
1666 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001667static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02001668parse_type_enum(struct lys_parser_ctx *ctx, const char **data, enum ly_stmt enum_kw, struct lysp_type_enum **enums)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001669{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001670 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001671 char *buf, *word;
David Sedlák6544c182019-07-12 13:17:33 +02001672 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001673 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001674 struct lysp_type_enum *enm;
1675
Radek Krejci2c4e7172018-10-19 15:56:26 +02001676 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001677
1678 /* get value */
Radek Krejcid6b76452019-09-03 17:03:03 +02001679 LY_CHECK_RET(get_argument(ctx, data, enum_kw == LY_STMT_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
1680 if (enum_kw == LY_STMT_ENUM) {
David Sedlák07869a52019-07-12 14:28:19 +02001681 ret = lysp_check_enum_name(ctx, (const char *)word, word_len);
David Sedlák6544c182019-07-12 13:17:33 +02001682 LY_CHECK_ERR_RET(ret, free(buf), ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001683 } /* else nothing specific for YANG_BIT */
Radek Krejci8b764662018-11-14 14:15:13 +01001684
Radek Krejci44ceedc2018-10-02 15:54:31 +02001685 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001686 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1687
Radek Krejci6d6556c2018-11-08 09:37:45 +01001688 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001689 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001690 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001691 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 +02001692 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001693 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02001694 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001695 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 +02001696 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001697 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001698 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 +02001699 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001700 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001701 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001702 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001703 case LY_STMT_VALUE:
1704 LY_CHECK_ERR_RET(enum_kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
David Sedlák9fb515f2019-07-11 10:33:58 +02001705 ly_stmt2str(enum_kw)), LY_EVALID);
1706 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
1707 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001708 case LY_STMT_POSITION:
1709 LY_CHECK_ERR_RET(enum_kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
David Sedlák9fb515f2019-07-11 10:33:58 +02001710 ly_stmt2str(enum_kw)), LY_EVALID);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001711 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001712 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001713 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001714 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001715 break;
1716 default:
David Sedlákb3077192019-06-19 10:55:37 +02001717 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001718 return LY_EVALID;
1719 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001720 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001721 return ret;
1722}
1723
Michal Vaskoea5abea2018-09-18 13:10:54 +02001724/**
1725 * @brief Parse the fraction-digits statement. Substatement of type statement.
1726 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001727 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001728 * @param[in,out] data Data to read from, always moved to currently handled character.
1729 * @param[in,out] fracdig Value to write to.
1730 * @param[in,out] exts Extension instances to add to.
1731 *
1732 * @return LY_ERR values.
1733 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001734static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001735parse_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 +02001736{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001737 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001738 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001739 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001740 unsigned long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02001741 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001742
1743 if (*fracdig) {
David Sedlákb3077192019-06-19 10:55:37 +02001744 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001745 return LY_EVALID;
1746 }
1747
1748 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001749 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001750
1751 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
David Sedlákb3077192019-06-19 10:55:37 +02001752 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001753 free(buf);
1754 return LY_EVALID;
1755 }
1756
1757 errno = 0;
1758 num = strtoul(word, &ptr, 10);
1759 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001760 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001761 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001762 free(buf);
1763 return LY_EVALID;
1764 }
1765 if ((errno == ERANGE) || (num > 18)) {
David Sedlákb3077192019-06-19 10:55:37 +02001766 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001767 free(buf);
1768 return LY_EVALID;
1769 }
1770 *fracdig = num;
1771 free(buf);
1772
Radek Krejci6d6556c2018-11-08 09:37:45 +01001773 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001774 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001775 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001776 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001777 break;
1778 default:
David Sedlákb3077192019-06-19 10:55:37 +02001779 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001780 return LY_EVALID;
1781 }
1782 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001783 return ret;
1784}
1785
Michal Vaskoea5abea2018-09-18 13:10:54 +02001786/**
1787 * @brief Parse the require-instance statement. Substatement of type statement.
1788 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001789 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001790 * @param[in,out] data Data to read from, always moved to currently handled character.
1791 * @param[in,out] reqinst Value to write to.
1792 * @param[in,out] flags Flags to write to.
1793 * @param[in,out] exts Extension instances to add to.
1794 *
1795 * @return LY_ERR values.
1796 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001797static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001798parse_type_reqinstance(struct lys_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001799 struct lysp_ext_instance **exts)
1800{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001801 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001802 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001803 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001804 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001805
1806 if (*flags & LYS_SET_REQINST) {
David Sedlákb3077192019-06-19 10:55:37 +02001807 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001808 return LY_EVALID;
1809 }
1810 *flags |= LYS_SET_REQINST;
1811
1812 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001813 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001814
1815 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1816 *reqinst = 1;
1817 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02001818 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001819 free(buf);
1820 return LY_EVALID;
1821 }
1822 free(buf);
1823
Radek Krejci6d6556c2018-11-08 09:37:45 +01001824 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001825 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001826 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001827 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001828 break;
1829 default:
David Sedlákb3077192019-06-19 10:55:37 +02001830 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001831 return LY_EVALID;
1832 }
1833 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001834 return ret;
1835}
1836
Michal Vaskoea5abea2018-09-18 13:10:54 +02001837/**
1838 * @brief Parse the modifier statement. Substatement of type pattern statement.
1839 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001840 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001841 * @param[in,out] data Data to read from, always moved to currently handled character.
1842 * @param[in,out] pat Value to write to.
1843 * @param[in,out] exts Extension instances to add to.
1844 *
1845 * @return LY_ERR values.
1846 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001847static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001848parse_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 +02001849{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001850 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001851 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001852 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001853 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001854
1855 if ((*pat)[0] == 0x15) {
David Sedlákb3077192019-06-19 10:55:37 +02001856 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001857 return LY_EVALID;
1858 }
1859
1860 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001861 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001862
1863 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02001864 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001865 free(buf);
1866 return LY_EVALID;
1867 }
1868 free(buf);
1869
1870 /* replace the value in the dictionary */
1871 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001872 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001873 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001874 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001875
1876 assert(buf[0] == 0x06);
1877 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02001878 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001879
Radek Krejci6d6556c2018-11-08 09:37:45 +01001880 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001881 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001882 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001883 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001884 break;
1885 default:
David Sedlákb3077192019-06-19 10:55:37 +02001886 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001887 return LY_EVALID;
1888 }
1889 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001890 return ret;
1891}
1892
Michal Vaskoea5abea2018-09-18 13:10:54 +02001893/**
1894 * @brief Parse the pattern statement. Substatement of type statement.
1895 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001896 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001897 * @param[in,out] data Data to read from, always moved to currently handled character.
1898 * @param[in,out] patterns Restrictions to add to.
1899 *
1900 * @return LY_ERR values.
1901 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001902static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001903parse_type_pattern(struct lys_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001904{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001905 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001906 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001907 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001908 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001909 struct lysp_restr *restr;
1910
Radek Krejci2c4e7172018-10-19 15:56:26 +02001911 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001912
1913 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001914 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001915
1916 /* add special meaning first byte */
1917 if (buf) {
1918 buf = realloc(buf, word_len + 2);
1919 word = buf;
1920 } else {
1921 buf = malloc(word_len + 2);
1922 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001923 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02001924 memmove(buf + 1, word, word_len);
1925 buf[0] = 0x06; /* pattern's default regular-match flag */
1926 buf[word_len + 1] = '\0'; /* terminating NULL byte */
1927 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001928
Radek Krejci6d6556c2018-11-08 09:37:45 +01001929 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001930 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001931 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001932 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 +02001933 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001934 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001935 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 +02001936 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001937 case LY_STMT_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001938 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 +02001939 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001940 case LY_STMT_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001941 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 +02001942 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001943 case LY_STMT_MODIFIER:
Radek Krejci335332a2019-09-05 13:03:35 +02001944 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001945 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001946 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001947 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001948 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001949 break;
1950 default:
David Sedlákb3077192019-06-19 10:55:37 +02001951 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001952 return LY_EVALID;
1953 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001954 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001955 return ret;
1956}
1957
Michal Vaskoea5abea2018-09-18 13:10:54 +02001958/**
1959 * @brief Parse the type statement.
1960 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001961 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001962 * @param[in,out] data Data to read from, always moved to currently handled character.
1963 * @param[in,out] type Type to wrote to.
1964 *
1965 * @return LY_ERR values.
1966 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001967static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001968parse_type(struct lys_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001969{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001970 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001971 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001972 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001973 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001974 struct lysp_type *nest_type;
1975
1976 if (type->name) {
David Sedlákb3077192019-06-19 10:55:37 +02001977 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001978 return LY_EVALID;
1979 }
1980
1981 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001982 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001983 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001984
Radek Krejci6d6556c2018-11-08 09:37:45 +01001985 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001986 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001987 case LY_STMT_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001988 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 +01001989 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001990 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001991 case LY_STMT_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001992 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01001993 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001994 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001995 case LY_STMT_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001996 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01001997 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001998 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001999 case LY_STMT_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002000 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002001 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002002 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002003 case LY_STMT_LENGTH:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002004 if (type->length) {
David Sedlákb3077192019-06-19 10:55:37 +02002005 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002006 return LY_EVALID;
2007 }
2008 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002009 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002010
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002011 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002012 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002013 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002014 case LY_STMT_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002015 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 +01002016 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002017 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002018 case LY_STMT_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002019 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002020 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002021 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002022 case LY_STMT_RANGE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002023 if (type->range) {
David Sedlákb3077192019-06-19 10:55:37 +02002024 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002025 return LY_EVALID;
2026 }
2027 type->range = calloc(1, sizeof *type->range);
David Sedlák7a8b2472019-07-11 15:08:34 +02002028 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002029
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002030 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002031 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002032 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002033 case LY_STMT_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002034 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002035 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002036 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002037 case LY_STMT_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002038 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2039 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002040 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002041 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002042 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002043 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002044 break;
2045 default:
David Sedlákb3077192019-06-19 10:55:37 +02002046 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002047 return LY_EVALID;
2048 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002049 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002050 return ret;
2051}
2052
Michal Vaskoea5abea2018-09-18 13:10:54 +02002053/**
2054 * @brief Parse the leaf statement.
2055 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002056 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002057 * @param[in,out] data Data to read from, always moved to currently handled character.
2058 * @param[in,out] siblings Siblings to add to.
2059 *
2060 * @return LY_ERR values.
2061 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002062LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002063parse_leaf(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002064{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002065 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002066 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002067 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002068 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002069 struct lysp_node_leaf *leaf;
2070
David Sedlák60adc092019-08-06 15:57:02 +02002071 /* create new leaf structure */
2072 LY_LIST_NEW_RET(ctx->ctx, siblings, leaf, next);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002073 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002074 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002075
Michal Vasko7fbc8162018-09-17 10:35:16 +02002076 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002077 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002078 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002079
2080 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002081 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002082 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002083 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002084 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002085 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002086 case LY_STMT_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002087 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 +02002088 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002089 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002090 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 +02002091 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002092 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002093 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 +02002094 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002095 case LY_STMT_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002096 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002097 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002098 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002099 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002100 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002101 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002102 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 +02002103 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002104 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002105 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002106 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002107 case LY_STMT_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002108 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002109 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002110 case LY_STMT_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002111 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 +02002112 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002113 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002114 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002115 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002116 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002117 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002118 break;
2119 default:
David Sedlákb3077192019-06-19 10:55:37 +02002120 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002121 return LY_EVALID;
2122 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002123 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002124 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002125checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002126 /* mandatory substatements */
2127 if (!leaf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002128 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002129 return LY_EVALID;
2130 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002131 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
David Sedlákb3077192019-06-19 10:55:37 +02002132 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002133 return LY_EVALID;
2134 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002135
2136 return ret;
2137}
2138
Michal Vaskoea5abea2018-09-18 13:10:54 +02002139/**
2140 * @brief Parse the max-elements statement.
2141 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002142 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002143 * @param[in,out] data Data to read from, always moved to currently handled character.
2144 * @param[in,out] max Value to write to.
2145 * @param[in,out] flags Flags to write to.
2146 * @param[in,out] exts Extension instances to add to.
2147 *
2148 * @return LY_ERR values.
2149 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002150LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002151parse_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 +02002152{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002153 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002154 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002155 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002156 unsigned long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02002157 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002158
2159 if (*flags & LYS_SET_MAX) {
David Sedlákb3077192019-06-19 10:55:37 +02002160 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002161 return LY_EVALID;
2162 }
2163 *flags |= LYS_SET_MAX;
2164
2165 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002166 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002167
2168 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
David Sedlákb3077192019-06-19 10:55:37 +02002169 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002170 free(buf);
2171 return LY_EVALID;
2172 }
2173
2174 if (strncmp(word, "unbounded", word_len)) {
2175 errno = 0;
2176 num = strtoul(word, &ptr, 10);
2177 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002178 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002179 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002180 free(buf);
2181 return LY_EVALID;
2182 }
2183 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002184 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002185 free(buf);
2186 return LY_EVALID;
2187 }
2188
2189 *max = num;
2190 }
2191 free(buf);
2192
Radek Krejci6d6556c2018-11-08 09:37:45 +01002193 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002194 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002195 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002196 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002197 break;
2198 default:
David Sedlákb3077192019-06-19 10:55:37 +02002199 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002200 return LY_EVALID;
2201 }
2202 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002203 return ret;
2204}
2205
Michal Vaskoea5abea2018-09-18 13:10:54 +02002206/**
2207 * @brief Parse the min-elements statement.
2208 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002209 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002210 * @param[in,out] data Data to read from, always moved to currently handled character.
2211 * @param[in,out] min Value to write to.
2212 * @param[in,out] flags Flags to write to.
2213 * @param[in,out] exts Extension instances to add to.
2214 *
2215 * @return LY_ERR values.
2216 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002217LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002218parse_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 +02002219{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002220 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002221 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002222 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002223 unsigned long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02002224 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002225
2226 if (*flags & LYS_SET_MIN) {
David Sedlákb3077192019-06-19 10:55:37 +02002227 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002228 return LY_EVALID;
2229 }
2230 *flags |= LYS_SET_MIN;
2231
2232 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002233 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002234
2235 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
David Sedlákb3077192019-06-19 10:55:37 +02002236 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002237 free(buf);
2238 return LY_EVALID;
2239 }
2240
2241 errno = 0;
2242 num = strtoul(word, &ptr, 10);
2243 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002244 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002245 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002246 free(buf);
2247 return LY_EVALID;
2248 }
2249 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002250 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002251 free(buf);
2252 return LY_EVALID;
2253 }
2254 *min = num;
2255 free(buf);
2256
Radek Krejci6d6556c2018-11-08 09:37:45 +01002257 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002258 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002259 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002260 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002261 break;
2262 default:
David Sedlákb3077192019-06-19 10:55:37 +02002263 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002264 return LY_EVALID;
2265 }
2266 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002267 return ret;
2268}
2269
Michal Vaskoea5abea2018-09-18 13:10:54 +02002270/**
2271 * @brief Parse the ordered-by statement.
2272 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002273 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002274 * @param[in,out] data Data to read from, always moved to currently handled character.
2275 * @param[in,out] flags Flags to write to.
2276 * @param[in,out] exts Extension instances to add to.
2277 *
2278 * @return LY_ERR values.
2279 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002280static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002281parse_orderedby(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002282{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002283 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002284 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002285 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002286 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002287
2288 if (*flags & LYS_ORDBY_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02002289 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002290 return LY_EVALID;
2291 }
2292
2293 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002294 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002295
2296 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2297 *flags |= LYS_ORDBY_SYSTEM;
2298 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2299 *flags |= LYS_ORDBY_USER;
2300 } else {
David Sedlákb3077192019-06-19 10:55:37 +02002301 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002302 free(buf);
2303 return LY_EVALID;
2304 }
2305 free(buf);
2306
Radek Krejci6d6556c2018-11-08 09:37:45 +01002307 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002308 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002309 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002310 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002311 break;
2312 default:
David Sedlákb3077192019-06-19 10:55:37 +02002313 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002314 return LY_EVALID;
2315 }
2316 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002317 return ret;
2318}
2319
Michal Vaskoea5abea2018-09-18 13:10:54 +02002320/**
2321 * @brief Parse the leaf-list statement.
2322 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002323 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002324 * @param[in,out] data Data to read from, always moved to currently handled character.
2325 * @param[in,out] siblings Siblings to add to.
2326 *
2327 * @return LY_ERR values.
2328 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002329LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002330parse_leaflist(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002331{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002332 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002333 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002334 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002335 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002336 struct lysp_node_leaflist *llist;
2337
David Sedlák60adc092019-08-06 15:57:02 +02002338 /* create new leaf-list structure */
2339 LY_LIST_NEW_RET(ctx->ctx, siblings, llist, next);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002340 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002341 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002342
Michal Vasko7fbc8162018-09-17 10:35:16 +02002343 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002344 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002345 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002346
2347 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002348 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002349 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002350 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002351 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002352 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002353 case LY_STMT_DEFAULT:
Radek Krejci335332a2019-09-05 13:03:35 +02002354 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002355 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 +02002356 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002357 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002358 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 +02002359 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002360 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002361 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 +02002362 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002363 case LY_STMT_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002364 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002365 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002366 case LY_STMT_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002367 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002368 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002369 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002370 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002371 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002372 case LY_STMT_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002373 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002374 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002375 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002376 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 +02002377 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002378 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002379 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002380 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002381 case LY_STMT_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002382 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002383 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002384 case LY_STMT_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002385 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 +02002386 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002387 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002388 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002389 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002390 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002391 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002392 break;
2393 default:
David Sedlákb3077192019-06-19 10:55:37 +02002394 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002395 return LY_EVALID;
2396 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002397 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002398 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002399checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002400 /* mandatory substatements */
2401 if (!llist->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002402 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002403 return LY_EVALID;
2404 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002405 if ((llist->min) && (llist->dflts)) {
David Sedlákb3077192019-06-19 10:55:37 +02002406 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
Radek Krejci0e5d8382018-11-28 16:37:53 +01002407 return LY_EVALID;
2408 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002409 if (llist->max && llist->min > llist->max) {
David Sedlákb3077192019-06-19 10:55:37 +02002410 LOGVAL_PARSER(ctx, LYVE_SEMANTICS,
Radek Krejcidf6cad12018-11-28 17:10:55 +01002411 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2412 llist->min, llist->max);
2413 return LY_EVALID;
2414 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002415
2416 return ret;
2417}
2418
Michal Vaskoea5abea2018-09-18 13:10:54 +02002419/**
2420 * @brief Parse the refine statement.
2421 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002422 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002423 * @param[in,out] data Data to read from, always moved to currently handled character.
2424 * @param[in,out] refines Refines to add to.
2425 *
2426 * @return LY_ERR values.
2427 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002428static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002429parse_refine(struct lys_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002430{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002431 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002432 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002433 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002434 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002435 struct lysp_refine *rf;
2436
Radek Krejci2c4e7172018-10-19 15:56:26 +02002437 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002438
2439 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002440 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
David Sedlákb9b892c2019-07-12 14:44:02 +02002441 YANG_CHECK_NONEMPTY(ctx, word_len, "refine");
Radek Krejci44ceedc2018-10-02 15:54:31 +02002442 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002443
Radek Krejci6d6556c2018-11-08 09:37:45 +01002444 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002445 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002446 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002447 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002448 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002449 case LY_STMT_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002450 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 +02002451 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002452 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002453 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 +02002454 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002455 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02002456 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002457 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 +02002458 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002459 case LY_STMT_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002460 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002461 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002462 case LY_STMT_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002463 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002464 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002465 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002466 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002467 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002468 case LY_STMT_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002469 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002470 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002471 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002472 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 +02002473 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002474 case LY_STMT_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002475 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 +02002476 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002477 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002478 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002479 break;
2480 default:
David Sedlákb3077192019-06-19 10:55:37 +02002481 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002482 return LY_EVALID;
2483 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002484 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002485 return ret;
2486}
2487
Michal Vaskoea5abea2018-09-18 13:10:54 +02002488/**
2489 * @brief Parse the typedef statement.
2490 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002491 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002492 * @param[in,out] data Data to read from, always moved to currently handled character.
2493 * @param[in,out] typedefs Typedefs to add to.
2494 *
2495 * @return LY_ERR values.
2496 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002497static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002498parse_typedef(struct lys_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002499{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002500 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002501 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002502 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002503 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002504 struct lysp_tpdf *tpdf;
2505
Radek Krejci2c4e7172018-10-19 15:56:26 +02002506 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002507
2508 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002509 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002510 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002511
2512 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002513 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002514 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002515 case LY_STMT_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002516 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 +02002517 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002518 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002519 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 +02002520 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002521 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002522 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 +02002523 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002524 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002525 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002526 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002527 case LY_STMT_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002528 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002529 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002530 case LY_STMT_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002531 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 +02002532 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002533 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002534 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002535 break;
2536 default:
David Sedlákb3077192019-06-19 10:55:37 +02002537 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002538 return LY_EVALID;
2539 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002540 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002541 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002542checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002543 /* mandatory substatements */
2544 if (!tpdf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002545 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002546 return LY_EVALID;
2547 }
2548
Radek Krejcibbe09a92018-11-08 09:36:54 +01002549 /* store data for collision check */
Radek Krejci7fc68292019-06-12 13:51:09 +02002550 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
David Sedláke8b74df2019-08-14 14:18:22 +02002551 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0) == -1, LY_EMEM);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002552 }
2553
Michal Vasko7fbc8162018-09-17 10:35:16 +02002554 return ret;
2555}
2556
Michal Vaskoea5abea2018-09-18 13:10:54 +02002557/**
2558 * @brief Parse the input or output statement.
2559 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002560 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002561 * @param[in,out] data Data to read from, always moved to currently handled character.
2562 * @param[in] kw Type of this particular keyword
2563 * @param[in,out] inout_p Input/output pointer to write to.
2564 *
2565 * @return LY_ERR values.
2566 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002567static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02002568parse_inout(struct lys_parser_ctx *ctx, const char **data, enum ly_stmt inout_kw, struct lysp_node *parent, struct lysp_action_inout *inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002569{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002570 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002571 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002572 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002573 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002574
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002575 if (inout_p->nodetype) {
David Sedlákb3077192019-06-19 10:55:37 +02002576 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002577 return LY_EVALID;
2578 }
2579
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002580 /* initiate structure */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002581 inout_p->nodetype = &((struct lysp_action*)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002582 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002583
2584 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02002585 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002586 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002587 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002588 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci10113652018-11-14 16:56:50 +01002589 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002590 case LY_STMT_ANYXML:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002591 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002592 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002593 case LY_STMT_CHOICE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002594 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002595 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002596 case LY_STMT_CONTAINER:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002597 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002598 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002599 case LY_STMT_LEAF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002600 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002601 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002602 case LY_STMT_LEAF_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002603 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002604 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002605 case LY_STMT_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002606 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002607 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002608 case LY_STMT_USES:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002609 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002610 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002611 case LY_STMT_TYPEDEF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002612 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002613 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002614 case LY_STMT_MUST:
Radek Krejci335332a2019-09-05 13:03:35 +02002615 PARSER_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002616 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002617 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002618 case LY_STMT_GROUPING:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002619 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002620 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002621 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002622 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002623 break;
2624 default:
David Sedlákb3077192019-06-19 10:55:37 +02002625 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002626 return LY_EVALID;
2627 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002628 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002629 LY_CHECK_RET(ret);
2630checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002631 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02002632 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, inout_p->groupings, NULL, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02002633
Michal Vasko7fbc8162018-09-17 10:35:16 +02002634 return ret;
2635}
2636
Michal Vaskoea5abea2018-09-18 13:10:54 +02002637/**
2638 * @brief Parse the action statement.
2639 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002640 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002641 * @param[in,out] data Data to read from, always moved to currently handled character.
2642 * @param[in,out] actions Actions to add to.
2643 *
2644 * @return LY_ERR values.
2645 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002646LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002647parse_action(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002648{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002649 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002650 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002651 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002652 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002653 struct lysp_action *act;
2654
Radek Krejci2c4e7172018-10-19 15:56:26 +02002655 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002656
2657 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002658 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002659 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002660 act->nodetype = LYS_ACTION;
2661 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002662
Radek Krejci7fc68292019-06-12 13:51:09 +02002663 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002664 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002665 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002666 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 +02002667 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002668 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002669 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 +02002670 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002671 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002672 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 +02002673 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002674 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002675 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002676 break;
2677
Radek Krejcid6b76452019-09-03 17:03:03 +02002678 case LY_STMT_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002679 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002680 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002681 case LY_STMT_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002682 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002683 break;
2684
Radek Krejcid6b76452019-09-03 17:03:03 +02002685 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002686 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002687 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002688 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002689 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002690 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002691 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002692 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002693 break;
2694 default:
David Sedlákb3077192019-06-19 10:55:37 +02002695 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002696 return LY_EVALID;
2697 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002698 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002699 LY_CHECK_RET(ret);
2700checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002701 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02002702 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, act->groupings, NULL, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02002703
Michal Vasko7fbc8162018-09-17 10:35:16 +02002704 return ret;
2705}
2706
Michal Vaskoea5abea2018-09-18 13:10:54 +02002707/**
2708 * @brief Parse the notification statement.
2709 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002710 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002711 * @param[in,out] data Data to read from, always moved to currently handled character.
2712 * @param[in,out] notifs Notifications to add to.
2713 *
2714 * @return LY_ERR values.
2715 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002716LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002717parse_notif(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002718{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002719 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002720 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002721 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002722 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002723 struct lysp_notif *notif;
2724
Radek Krejci2c4e7172018-10-19 15:56:26 +02002725 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002726
2727 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002728 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002729 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002730 notif->nodetype = LYS_NOTIF;
2731 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002732
Radek Krejci7fc68292019-06-12 13:51:09 +02002733 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002734 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002735 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002736 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 +02002737 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002738 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002739 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 +02002740 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002741 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002742 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 +02002743 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002744 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002745 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002746 break;
2747
Radek Krejcid6b76452019-09-03 17:03:03 +02002748 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002749 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci10113652018-11-14 16:56:50 +01002750 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002751 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002752 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002753 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002754 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002755 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002756 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002757 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002758 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002759 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002760 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002761 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002762 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002763 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002764 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002765 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002766 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002767 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002768 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002769 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002770 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002771 break;
2772
Radek Krejcid6b76452019-09-03 17:03:03 +02002773 case LY_STMT_MUST:
Radek Krejci335332a2019-09-05 13:03:35 +02002774 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002775 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002776 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002777 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002778 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002779 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002780 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002781 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002782 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002783 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002784 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002785 break;
2786 default:
David Sedlákb3077192019-06-19 10:55:37 +02002787 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002788 return LY_EVALID;
2789 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002791 LY_CHECK_RET(ret);
2792checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002793 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02002794 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, notif->groupings, NULL, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02002795
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 return ret;
2797}
2798
Michal Vaskoea5abea2018-09-18 13:10:54 +02002799/**
2800 * @brief Parse the grouping statement.
2801 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002802 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002803 * @param[in,out] data Data to read from, always moved to currently handled character.
2804 * @param[in,out] groupings Groupings to add to.
2805 *
2806 * @return LY_ERR values.
2807 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002808LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002809parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002810{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002811 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002812 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002813 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002814 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002815 struct lysp_grp *grp;
2816
Radek Krejci2c4e7172018-10-19 15:56:26 +02002817 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002818
2819 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002820 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002821 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002822 grp->nodetype = LYS_GROUPING;
2823 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002824
Radek Krejci7fc68292019-06-12 13:51:09 +02002825 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002826 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002827 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002828 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 +02002829 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002830 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002831 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 +02002832 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002833 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002834 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002835 break;
2836
Radek Krejcid6b76452019-09-03 17:03:03 +02002837 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002838 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci10113652018-11-14 16:56:50 +01002839 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002840 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002841 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002842 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002843 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002844 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002845 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002846 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002847 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002848 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002849 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002850 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002851 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002852 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002853 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002854 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002855 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002856 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002858 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002859 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860 break;
2861
Radek Krejcid6b76452019-09-03 17:03:03 +02002862 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002863 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002864 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002865 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02002866 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002867 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002868 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002869 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002870 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002871 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002872 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02002873 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002874 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002875 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002876 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002877 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002878 break;
2879 default:
David Sedlákb3077192019-06-19 10:55:37 +02002880 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002881 return LY_EVALID;
2882 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002883 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002884 LY_CHECK_RET(ret);
2885checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002886 /* finalize parent pointers to the reallocated items */
David Sedlák0d6de5a2019-07-22 13:25:44 +02002887 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, grp->groupings, NULL, grp->actions, grp->notifs));
Radek Krejci7fc68292019-06-12 13:51:09 +02002888
Michal Vasko7fbc8162018-09-17 10:35:16 +02002889 return ret;
2890}
2891
Michal Vaskoea5abea2018-09-18 13:10:54 +02002892/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02002893 * @brief Parse the augment statement.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002894 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002895 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002896 * @param[in,out] data Data to read from, always moved to currently handled character.
2897 * @param[in,out] augments Augments to add to.
2898 *
2899 * @return LY_ERR values.
2900 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002901LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002902parse_augment(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002903{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002904 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002905 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002906 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002907 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002908 struct lysp_augment *aug;
2909
Radek Krejci2c4e7172018-10-19 15:56:26 +02002910 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002911
2912 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002913 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
David Sedlákb9b892c2019-07-12 14:44:02 +02002914 YANG_CHECK_NONEMPTY(ctx, word_len, "augment");
Radek Krejci44ceedc2018-10-02 15:54:31 +02002915 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002916 aug->nodetype = LYS_AUGMENT;
2917 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002918
Radek Krejci7fc68292019-06-12 13:51:09 +02002919 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002920 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002921 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002922 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 +02002923 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002924 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002925 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 +02002926 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002927 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002928 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 +02002929 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002930 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002931 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002932 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002933 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002934 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002935 break;
2936
Radek Krejcid6b76452019-09-03 17:03:03 +02002937 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002938 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci10113652018-11-14 16:56:50 +01002939 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002940 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002941 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002942 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002943 case LY_STMT_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002944 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002945 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002946 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002947 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002948 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002949 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002950 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002951 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002952 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002953 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002954 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002955 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002956 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002957 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002958 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002959 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002960 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002961 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002962 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002963 break;
2964
Radek Krejcid6b76452019-09-03 17:03:03 +02002965 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02002966 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002967 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002968 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002969 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02002970 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002971 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002972 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002973 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002974 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002975 break;
2976 default:
David Sedlákb3077192019-06-19 10:55:37 +02002977 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978 return LY_EVALID;
2979 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002980 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002981 LY_CHECK_RET(ret);
2982checks:
2983 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02002984 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, NULL, NULL, aug->actions, aug->notifs));
Radek Krejci7fc68292019-06-12 13:51:09 +02002985
Michal Vasko7fbc8162018-09-17 10:35:16 +02002986 return ret;
2987}
2988
Michal Vaskoea5abea2018-09-18 13:10:54 +02002989/**
2990 * @brief Parse the uses statement.
2991 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002992 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002993 * @param[in,out] data Data to read from, always moved to currently handled character.
2994 * @param[in,out] siblings Siblings to add to.
2995 *
2996 * @return LY_ERR values.
2997 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002998LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002999parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003000{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003001 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003002 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003003 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003004 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003005 struct lysp_node_uses *uses;
3006
David Sedlák60adc092019-08-06 15:57:02 +02003007 /* create uses structure */
3008 LY_LIST_NEW_RET(ctx->ctx, siblings, uses, next);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003009 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003010 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003011
Michal Vasko7fbc8162018-09-17 10:35:16 +02003012 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003013 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003014 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003015
3016 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003017 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003018 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003019 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003020 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 +02003021 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003022 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003023 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 +02003024 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003025 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003026 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 +02003027 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003028 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003029 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003030 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003031 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003032 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003033 break;
3034
Radek Krejcid6b76452019-09-03 17:03:03 +02003035 case LY_STMT_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003036 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003037 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003038 case LY_STMT_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003039 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003040 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003041 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003042 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003043 break;
3044 default:
David Sedlákb3077192019-06-19 10:55:37 +02003045 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003046 return LY_EVALID;
3047 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003048 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003049checks:
3050 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02003051 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, NULL, uses->augments, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02003052
Michal Vasko7fbc8162018-09-17 10:35:16 +02003053 return ret;
3054}
3055
Michal Vaskoea5abea2018-09-18 13:10:54 +02003056/**
3057 * @brief Parse the case statement.
3058 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003059 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003060 * @param[in,out] data Data to read from, always moved to currently handled character.
3061 * @param[in,out] siblings Siblings to add to.
3062 *
3063 * @return LY_ERR values.
3064 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003065LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003066parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003067{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003068 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003069 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003070 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003071 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003072 struct lysp_node_case *cas;
3073
David Sedlák60adc092019-08-06 15:57:02 +02003074 /* create new case structure */
3075 LY_LIST_NEW_RET(ctx->ctx, siblings, cas, next);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003077 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003078
Michal Vasko7fbc8162018-09-17 10:35:16 +02003079 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003080 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003081 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003082
3083 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003084 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003085 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003086 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003087 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 +02003088 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003089 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003090 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 +02003091 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003092 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003093 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 +02003094 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003095 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003096 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003097 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003098 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003099 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003100 break;
3101
Radek Krejcid6b76452019-09-03 17:03:03 +02003102 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003103 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci10113652018-11-14 16:56:50 +01003104 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003105 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003106 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003107 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003108 case LY_STMT_CHOICE:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003109 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003110 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003111 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003112 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003113 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003114 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003115 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003116 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003117 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003118 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003119 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003120 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003121 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003122 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003123 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003124 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003125 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003126 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003127 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003128 break;
3129 default:
David Sedlákb3077192019-06-19 10:55:37 +02003130 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003131 return LY_EVALID;
3132 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003133 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003134 return ret;
3135}
3136
Michal Vaskoea5abea2018-09-18 13:10:54 +02003137/**
3138 * @brief Parse the choice statement.
3139 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003140 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003141 * @param[in,out] data Data to read from, always moved to currently handled character.
3142 * @param[in,out] siblings Siblings to add to.
3143 *
3144 * @return LY_ERR values.
3145 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003146LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003147parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003148{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003149 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003150 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003151 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003152 enum ly_stmt kw;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003153 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003154
David Sedlák60adc092019-08-06 15:57:02 +02003155 /* create new choice structure */
3156 LY_LIST_NEW_RET(ctx->ctx, siblings, choice, next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003157 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003158 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003159
Michal Vasko7fbc8162018-09-17 10:35:16 +02003160 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003161 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003162 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003163
3164 /* parse substatements */
Radek Krejcia9026eb2018-12-12 16:04:47 +01003165 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003166 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003167 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003168 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003169 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003170 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003171 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 +02003172 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003173 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003174 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 +02003175 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003176 case LY_STMT_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003177 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003178 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003179 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003180 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 +02003181 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003182 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003183 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003184 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003185 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003186 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003187 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003188 case LY_STMT_DEFAULT:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003189 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 +02003190 break;
3191
Radek Krejcid6b76452019-09-03 17:03:03 +02003192 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003193 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci10113652018-11-14 16:56:50 +01003194 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003195 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003196 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003197 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003198 case LY_STMT_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003199 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003200 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003201 case LY_STMT_CHOICE:
Radek Krejci335332a2019-09-05 13:03:35 +02003202 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003203 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003204 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003205 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003206 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003207 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003208 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003209 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003210 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003211 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003212 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003213 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003214 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003215 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003216 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003217 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003218 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003219 break;
3220 default:
David Sedlákb3077192019-06-19 10:55:37 +02003221 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003222 return LY_EVALID;
3223 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224 }
Radek Krejcia9026eb2018-12-12 16:04:47 +01003225 LY_CHECK_RET(ret);
3226checks:
3227 if ((choice->flags & LYS_MAND_TRUE) && choice->dflt) {
David Sedlákb3077192019-06-19 10:55:37 +02003228 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "choice");
Radek Krejcia9026eb2018-12-12 16:04:47 +01003229 return LY_EVALID;
3230 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003231 return ret;
3232}
3233
Michal Vaskoea5abea2018-09-18 13:10:54 +02003234/**
3235 * @brief Parse the container statement.
3236 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003237 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003238 * @param[in,out] data Data to read from, always moved to currently handled character.
3239 * @param[in,out] siblings Siblings to add to.
3240 *
3241 * @return LY_ERR values.
3242 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003243LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003244parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003245{
3246 LY_ERR ret = 0;
3247 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003248 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003249 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003250 struct lysp_node_container *cont;
3251
David Sedlák60adc092019-08-06 15:57:02 +02003252 /* create new container structure */
3253 LY_LIST_NEW_RET(ctx->ctx, siblings, cont, next);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003254 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003255 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003256
Michal Vasko7fbc8162018-09-17 10:35:16 +02003257 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003258 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003259 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003260
3261 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003262 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003263 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003264 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003265 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003266 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003267 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003268 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 +02003269 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003270 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003271 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 +02003272 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003273 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003274 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 +02003275 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003276 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003277 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003278 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003279 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003280 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003281 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003282 case LY_STMT_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003283 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 +02003284 break;
3285
Radek Krejcid6b76452019-09-03 17:03:03 +02003286 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003287 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci10113652018-11-14 16:56:50 +01003288 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003289 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003290 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003291 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003292 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003293 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003294 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003295 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003296 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003298 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003299 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003300 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003301 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003302 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003303 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003304 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003305 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003306 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003307 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003308 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003309 break;
3310
Radek Krejcid6b76452019-09-03 17:03:03 +02003311 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003312 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003313 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003314 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003315 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003316 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003317 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02003318 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003319 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003320 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003321 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003322 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003323 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003324 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02003325 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003326 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003327 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003328 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003329 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003330 break;
3331 default:
David Sedlákb3077192019-06-19 10:55:37 +02003332 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003333 return LY_EVALID;
3334 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003335 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003336checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003337 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02003338 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, cont->groupings, NULL, cont->actions, cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003339 return ret;
3340}
3341
Michal Vaskoea5abea2018-09-18 13:10:54 +02003342/**
3343 * @brief Parse the list statement.
3344 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003345 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003346 * @param[in,out] data Data to read from, always moved to currently handled character.
3347 * @param[in,out] siblings Siblings to add to.
3348 *
3349 * @return LY_ERR values.
3350 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003351LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003352parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003353{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003354 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003355 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003356 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003357 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003358 struct lysp_node_list *list;
3359
David Sedlák60adc092019-08-06 15:57:02 +02003360 /* create new list structure */
3361 LY_LIST_NEW_RET(ctx->ctx, siblings, list, next);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003362 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003363 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003364
Michal Vasko7fbc8162018-09-17 10:35:16 +02003365 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003366 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003367 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003368
3369 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003370 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003371 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003372 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003373 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003374 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003375 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003376 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 +02003377 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003378 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003379 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 +02003380 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003381 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003382 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 +02003383 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003384 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003385 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003386 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003387 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003388 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003389 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003390 case LY_STMT_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003391 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 +02003392 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003393 case LY_STMT_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003394 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003395 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003396 case LY_STMT_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003397 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003398 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003399 case LY_STMT_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003400 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003401 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003402 case LY_STMT_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003403 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 +02003404 break;
3405
Radek Krejcid6b76452019-09-03 17:03:03 +02003406 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003407 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci10113652018-11-14 16:56:50 +01003408 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003409 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003410 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003411 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003412 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003413 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003414 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003415 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003416 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003417 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003418 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003419 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003420 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003421 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003422 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003423 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003424 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003425 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003426 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003427 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003428 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003429 break;
3430
Radek Krejcid6b76452019-09-03 17:03:03 +02003431 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003432 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003433 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003434 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003435 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003436 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003437 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02003438 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003439 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003440 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003441 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003442 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003443 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003444 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02003445 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003446 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003447 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003448 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003449 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003450 break;
3451 default:
David Sedlákb3077192019-06-19 10:55:37 +02003452 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003453 return LY_EVALID;
3454 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003455 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003456 LY_CHECK_RET(ret);
3457checks:
Radek Krejci7fc68292019-06-12 13:51:09 +02003458 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02003459 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, list->groupings, NULL, list->actions, list->notifs));
Radek Krejci7fc68292019-06-12 13:51:09 +02003460
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003461 if (list->max && list->min > list->max) {
David Sedlákb3077192019-06-19 10:55:37 +02003462 LOGVAL_PARSER(ctx, LYVE_SEMANTICS,
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003463 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3464 list->min, list->max);
3465 return LY_EVALID;
3466 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003467
3468 return ret;
3469}
3470
Michal Vaskoea5abea2018-09-18 13:10:54 +02003471/**
3472 * @brief Parse the yin-element statement.
3473 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003474 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003475 * @param[in,out] data Data to read from, always moved to currently handled character.
3476 * @param[in,out] flags Flags to write to.
3477 * @param[in,out] exts Extension instances to add to.
3478 *
3479 * @return LY_ERR values.
3480 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003481static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003482parse_yinelement(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003483{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003484 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003485 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003486 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003487 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003488
3489 if (*flags & LYS_YINELEM_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02003490 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003491 return LY_EVALID;
3492 }
3493
3494 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003495 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003496
3497 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3498 *flags |= LYS_YINELEM_TRUE;
3499 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3500 *flags |= LYS_YINELEM_FALSE;
3501 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003502 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003503 free(buf);
3504 return LY_EVALID;
3505 }
3506 free(buf);
3507
Radek Krejci6d6556c2018-11-08 09:37:45 +01003508 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003509 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003510 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003511 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3512 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003513 default:
David Sedlákb3077192019-06-19 10:55:37 +02003514 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003515 return LY_EVALID;
3516 }
3517 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003518 return ret;
3519}
3520
Michal Vaskoea5abea2018-09-18 13:10:54 +02003521/**
David Sedlák2444f8f2019-07-09 11:02:47 +02003522 * @brief Parse the argument statement.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003523 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003524 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003525 * @param[in,out] data Data to read from, always moved to currently handled character.
3526 * @param[in,out] argument Value to write to.
3527 * @param[in,out] flags Flags to write to.
3528 * @param[in,out] exts Extension instances to add to.
3529 *
3530 * @return LY_ERR values.
3531 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003532static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003533parse_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 +02003534{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003535 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003536 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003537 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003538 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003539
3540 if (*argument) {
David Sedlákb3077192019-06-19 10:55:37 +02003541 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003542 return LY_EVALID;
3543 }
3544
3545 /* get value */
David Sedlák2444f8f2019-07-09 11:02:47 +02003546 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003547 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003548
Radek Krejci6d6556c2018-11-08 09:37:45 +01003549 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003550 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003551 case LY_STMT_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003552 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003553 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003554 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003555 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003556 break;
3557 default:
David Sedlákb3077192019-06-19 10:55:37 +02003558 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003559 return LY_EVALID;
3560 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003561 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003562 return ret;
3563}
3564
Michal Vaskoea5abea2018-09-18 13:10:54 +02003565/**
3566 * @brief Parse the extension statement.
3567 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003568 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003569 * @param[in,out] data Data to read from, always moved to currently handled character.
3570 * @param[in,out] extensions Extensions to add to.
3571 *
3572 * @return LY_ERR values.
3573 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003574static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003575parse_extension(struct lys_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003576{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003577 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003578 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003579 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003580 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003581 struct lysp_ext *ex;
3582
Radek Krejci2c4e7172018-10-19 15:56:26 +02003583 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584
3585 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003586 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003587 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003588
Radek Krejci6d6556c2018-11-08 09:37:45 +01003589 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003591 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003592 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 +02003593 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003594 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003595 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 +02003596 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003597 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003598 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003599 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003600 case LY_STMT_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003601 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003602 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003603 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003604 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003605 break;
3606 default:
David Sedlákb3077192019-06-19 10:55:37 +02003607 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003608 return LY_EVALID;
3609 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003611 return ret;
3612}
3613
Michal Vaskoea5abea2018-09-18 13:10:54 +02003614/**
3615 * @brief Parse the deviate statement.
3616 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003617 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003618 * @param[in,out] data Data to read from, always moved to currently handled character.
3619 * @param[in,out] deviates Deviates to add to.
3620 *
3621 * @return LY_ERR values.
3622 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003623LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003624parse_deviate(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003625{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003626 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003627 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003628 size_t word_len, dev_mod;
Radek Krejcid6b76452019-09-03 17:03:03 +02003629 enum ly_stmt kw;
David Sedlák60adc092019-08-06 15:57:02 +02003630 struct lysp_deviate *d;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003631 struct lysp_deviate_add *d_add = NULL;
3632 struct lysp_deviate_rpl *d_rpl = NULL;
3633 struct lysp_deviate_del *d_del = NULL;
Radek Krejci4ad42aa2019-07-23 16:55:58 +02003634 const char **d_units = NULL, ***d_uniques = NULL, ***d_dflts = NULL;
3635 struct lysp_restr **d_musts = NULL;
3636 uint16_t *d_flags = 0;
3637 uint32_t *d_min = 0, *d_max = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003638
3639 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003640 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003641
3642 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3643 dev_mod = LYS_DEV_NOT_SUPPORTED;
3644 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3645 dev_mod = LYS_DEV_ADD;
3646 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3647 dev_mod = LYS_DEV_REPLACE;
3648 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3649 dev_mod = LYS_DEV_DELETE;
3650 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003651 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003652 free(buf);
3653 return LY_EVALID;
3654 }
3655 free(buf);
3656
3657 /* create structure */
3658 switch (dev_mod) {
3659 case LYS_DEV_NOT_SUPPORTED:
3660 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003661 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003662 break;
3663 case LYS_DEV_ADD:
3664 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003665 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003666 d = (struct lysp_deviate *)d_add;
3667 d_units = &d_add->units;
3668 d_uniques = &d_add->uniques;
3669 d_dflts = &d_add->dflts;
3670 d_musts = &d_add->musts;
3671 d_flags = &d_add->flags;
3672 d_min = &d_add->min;
3673 d_max = &d_add->max;
3674 break;
3675 case LYS_DEV_REPLACE:
3676 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003677 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003678 d = (struct lysp_deviate *)d_rpl;
3679 d_units = &d_rpl->units;
3680 d_flags = &d_rpl->flags;
3681 d_min = &d_rpl->min;
3682 d_max = &d_rpl->max;
3683 break;
3684 case LYS_DEV_DELETE:
3685 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003686 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003687 d = (struct lysp_deviate *)d_del;
3688 d_units = &d_del->units;
3689 d_uniques = &d_del->uniques;
3690 d_dflts = &d_del->dflts;
3691 d_musts = &d_del->musts;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003692 break;
3693 default:
3694 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003695 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003696 }
3697 d->mod = dev_mod;
3698
3699 /* insert into siblings */
David Sedlák60adc092019-08-06 15:57:02 +02003700 LY_LIST_INSERT(deviates, d, next);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003701
Radek Krejci6d6556c2018-11-08 09:37:45 +01003702 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003703 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003704 case LY_STMT_CONFIG:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003705 switch (dev_mod) {
3706 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003707 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003708 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003709 return LY_EVALID;
3710 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003711 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003712 break;
3713 }
3714 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003715 case LY_STMT_DEFAULT:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003716 switch (dev_mod) {
3717 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02003718 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003719 return LY_EVALID;
3720 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003721 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 +02003722 break;
3723 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003724 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 +02003725 break;
3726 }
3727 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003728 case LY_STMT_MANDATORY:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003729 switch (dev_mod) {
3730 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003731 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003732 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003733 return LY_EVALID;
3734 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003735 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003736 break;
3737 }
3738 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003739 case LY_STMT_MAX_ELEMENTS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003740 switch (dev_mod) {
3741 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003742 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003743 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003744 return LY_EVALID;
3745 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003746 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003747 break;
3748 }
3749 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003750 case LY_STMT_MIN_ELEMENTS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003751 switch (dev_mod) {
3752 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003753 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003754 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003755 return LY_EVALID;
3756 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003757 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003758 break;
3759 }
3760 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003761 case LY_STMT_MUST:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003762 switch (dev_mod) {
3763 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003764 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02003765 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003766 return LY_EVALID;
3767 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003768 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003769 break;
3770 }
3771 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003772 case LY_STMT_TYPE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003773 switch (dev_mod) {
3774 case LYS_DEV_NOT_SUPPORTED:
3775 case LYS_DEV_ADD:
3776 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003777 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003778 return LY_EVALID;
3779 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003780 if (d_rpl->type) {
David Sedlákb3077192019-06-19 10:55:37 +02003781 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003782 return LY_EVALID;
3783 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003784 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003785 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003786 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003787 break;
3788 }
3789 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003790 case LY_STMT_UNIQUE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003791 switch (dev_mod) {
3792 case LYS_DEV_NOT_SUPPORTED:
3793 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02003794 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003795 return LY_EVALID;
3796 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003797 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 +02003798 break;
3799 }
3800 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003801 case LY_STMT_UNITS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003802 switch (dev_mod) {
3803 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02003804 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003805 return LY_EVALID;
3806 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003807 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 +02003808 break;
3809 }
3810 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003811 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003812 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003813 break;
3814 default:
David Sedlákb3077192019-06-19 10:55:37 +02003815 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003816 return LY_EVALID;
3817 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003818 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003819 return ret;
3820}
3821
Michal Vaskoea5abea2018-09-18 13:10:54 +02003822/**
3823 * @brief Parse the deviation statement.
3824 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003825 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003826 * @param[in,out] data Data to read from, always moved to currently handled character.
3827 * @param[in,out] deviations Deviations to add to.
3828 *
3829 * @return LY_ERR values.
3830 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003831LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003832parse_deviation(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003833{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003834 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003835 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003836 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003837 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003838 struct lysp_deviation *dev;
3839
Radek Krejci2c4e7172018-10-19 15:56:26 +02003840 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003841
3842 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003843 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
David Sedlákb9b892c2019-07-12 14:44:02 +02003844 YANG_CHECK_NONEMPTY(ctx, word_len, "deviation");
Radek Krejci44ceedc2018-10-02 15:54:31 +02003845 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003846
Radek Krejci6d6556c2018-11-08 09:37:45 +01003847 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003848 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003849 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003850 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 +02003851 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003852 case LY_STMT_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003853 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003854 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003855 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003856 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 +02003857 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003858 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003859 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003860 break;
3861 default:
David Sedlákb3077192019-06-19 10:55:37 +02003862 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003863 return LY_EVALID;
3864 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003865 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003866 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01003867checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003868 /* mandatory substatements */
3869 if (!dev->deviates) {
David Sedlákb3077192019-06-19 10:55:37 +02003870 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003871 return LY_EVALID;
3872 }
3873
3874 return ret;
3875}
3876
Michal Vaskoea5abea2018-09-18 13:10:54 +02003877/**
3878 * @brief Parse the feature statement.
3879 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003880 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003881 * @param[in,out] data Data to read from, always moved to currently handled character.
3882 * @param[in,out] features Features to add to.
3883 *
3884 * @return LY_ERR values.
3885 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003886LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003887parse_feature(struct lys_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003888{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003889 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003890 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003891 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003892 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003893 struct lysp_feature *feat;
3894
Radek Krejci2c4e7172018-10-19 15:56:26 +02003895 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003896
3897 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003898 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003899 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01003900
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) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003903 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003904 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 +02003905 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003906 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003907 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 +02003908 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003909 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003910 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 +02003911 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003912 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003913 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003914 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003915 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003916 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003917 break;
3918 default:
David Sedlákb3077192019-06-19 10:55:37 +02003919 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003920 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003921 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003923 return ret;
3924}
3925
Michal Vaskoea5abea2018-09-18 13:10:54 +02003926/**
3927 * @brief Parse the identity statement.
3928 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003929 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003930 * @param[in,out] data Data to read from, always moved to currently handled character.
3931 * @param[in,out] identities Identities to add to.
3932 *
3933 * @return LY_ERR values.
3934 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003935LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003936parse_identity(struct lys_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003937{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003938 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003939 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003940 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003941 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003942 struct lysp_ident *ident;
3943
Radek Krejci2c4e7172018-10-19 15:56:26 +02003944 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003945
3946 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003947 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003948 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01003949
Radek Krejci6d6556c2018-11-08 09:37:45 +01003950 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003951 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003952 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003953 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 +02003954 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003955 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02003956 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003957 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 +02003958 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003959 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003960 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 +02003961 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003962 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003963 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003964 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003965 case LY_STMT_BASE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01003966 if (ident->bases && ctx->mod_version < 2) {
David Sedlákb3077192019-06-19 10:55:37 +02003967 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 +01003968 return LY_EVALID;
3969 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003970 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 +02003971 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003972 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003973 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003974 break;
3975 default:
David Sedlákb3077192019-06-19 10:55:37 +02003976 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003977 return LY_EVALID;
3978 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003979 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003980 return ret;
3981}
3982
Michal Vaskoea5abea2018-09-18 13:10:54 +02003983/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01003984 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003985 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003986 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003987 * @param[in,out] data Data to read from, always moved to currently handled character.
3988 * @param[in,out] mod Module to write to.
3989 *
3990 * @return LY_ERR values.
3991 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003992LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003993parse_module(struct lys_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003994{
3995 LY_ERR ret = 0;
3996 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003997 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003998 enum ly_stmt kw, prev_kw = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003999 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004000 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004001
4002 /* (sub)module name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004003 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004004 INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004005
Radek Krejci6d6556c2018-11-08 09:37:45 +01004006 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004007
Radek Krejcie3846472018-10-15 15:24:51 +02004008#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004009 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 +02004010
Michal Vasko7fbc8162018-09-17 10:35:16 +02004011 switch (kw) {
4012 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004013 case LY_STMT_NAMESPACE:
4014 case LY_STMT_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004015 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4016 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004017 case LY_STMT_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004018 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004019 break;
4020 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004021 case LY_STMT_INCLUDE:
4022 case LY_STMT_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004023 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004024 break;
4025 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004026 case LY_STMT_ORGANIZATION:
4027 case LY_STMT_CONTACT:
4028 case LY_STMT_DESCRIPTION:
4029 case LY_STMT_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004030 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004031 break;
4032
4033 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004034 case LY_STMT_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004035 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004036 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004037 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004038 case LY_STMT_ANYDATA:
4039 case LY_STMT_ANYXML:
4040 case LY_STMT_AUGMENT:
4041 case LY_STMT_CHOICE:
4042 case LY_STMT_CONTAINER:
4043 case LY_STMT_DEVIATION:
4044 case LY_STMT_EXTENSION:
4045 case LY_STMT_FEATURE:
4046 case LY_STMT_GROUPING:
4047 case LY_STMT_IDENTITY:
4048 case LY_STMT_LEAF:
4049 case LY_STMT_LEAF_LIST:
4050 case LY_STMT_LIST:
4051 case LY_STMT_NOTIFICATION:
4052 case LY_STMT_RPC:
4053 case LY_STMT_TYPEDEF:
4054 case LY_STMT_USES:
4055 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004056 mod_stmt = Y_MOD_BODY;
4057 break;
4058 default:
4059 /* error handled in the next switch */
4060 break;
4061 }
Radek Krejcie3846472018-10-15 15:24:51 +02004062#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004063
Radek Krejcie3846472018-10-15 15:24:51 +02004064 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004065 switch (kw) {
4066 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004067 case LY_STMT_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004068 LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
4069 ctx->mod_version = mod->mod->version;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004070 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004071 case LY_STMT_NAMESPACE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004072 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 +02004073 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004074 case LY_STMT_PREFIX:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004075 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 +02004076 break;
4077
4078 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004079 case LY_STMT_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004080 LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004081 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004082 case LY_STMT_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004083 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004084 break;
4085
4086 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004087 case LY_STMT_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004088 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 +02004089 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004090 case LY_STMT_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004091 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 +02004092 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004093 case LY_STMT_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004094 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 +02004095 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004096 case LY_STMT_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004097 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 +02004098 break;
4099
4100 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004101 case LY_STMT_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004102 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004103 break;
4104
4105 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004106 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02004107 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci10113652018-11-14 16:56:50 +01004108 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02004109 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004110 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004111 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004112 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004113 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004114 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004115 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004116 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004117 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004118 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004119 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004120 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004121 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004122 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004123 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004124 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004125 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004126 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004127 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004128 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004129 break;
4130
Radek Krejcid6b76452019-09-03 17:03:03 +02004131 case LY_STMT_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004132 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004133 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004134 case LY_STMT_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004135 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004136 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004137 case LY_STMT_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004138 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004139 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004140 case LY_STMT_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004141 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004142 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004143 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004144 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004145 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004146 case LY_STMT_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004147 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004148 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004149 case LY_STMT_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004150 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004151 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004152 case LY_STMT_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004153 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004154 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004155 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004156 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004157 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004158 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004159 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004160 break;
4161
4162 default:
David Sedlákb3077192019-06-19 10:55:37 +02004163 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004164 return LY_EVALID;
4165 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004166 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004167 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004168
Radek Krejci6d6556c2018-11-08 09:37:45 +01004169checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004170 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02004171 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004172
Michal Vasko7fbc8162018-09-17 10:35:16 +02004173 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004174 if (!mod->mod->ns) {
David Sedlákb3077192019-06-19 10:55:37 +02004175 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004176 return LY_EVALID;
4177 } else if (!mod->mod->prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02004178 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004179 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004180 }
4181
Radek Krejcie9e987e2018-10-31 12:50:27 +01004182 /* submodules share the namespace with the module names, so there must not be
4183 * a submodule of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004184 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->mod->name, NULL);
4185 if (dup) {
David Sedlákb3077192019-06-19 10:55:37 +02004186 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 +01004187 return LY_EVALID;
4188 }
4189
4190 return ret;
4191}
4192
4193/**
4194 * @brief Parse submodule substatements.
4195 *
4196 * @param[in] ctx yang parser context for logging.
4197 * @param[in,out] data Data to read from, always moved to currently handled character.
4198 * @param[out] submod Parsed submodule structure.
4199 *
4200 * @return LY_ERR values.
4201 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004202LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004203parse_submodule(struct lys_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004204{
4205 LY_ERR ret = 0;
4206 char *buf, *word;
4207 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004208 enum ly_stmt kw, prev_kw = 0;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004209 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4210 struct lysp_submodule *dup;
4211
4212 /* submodule name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004213 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004214 INSERT_WORD(ctx, buf, submod->name, word, word_len);
4215
4216 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
4217
4218#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004219 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 +01004220
4221 switch (kw) {
4222 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004223 case LY_STMT_BELONGS_TO:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004224 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4225 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004226 case LY_STMT_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004227 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4228 break;
4229 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004230 case LY_STMT_INCLUDE:
4231 case LY_STMT_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004232 CHECK_ORDER(Y_MOD_LINKAGE);
4233 break;
4234 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004235 case LY_STMT_ORGANIZATION:
4236 case LY_STMT_CONTACT:
4237 case LY_STMT_DESCRIPTION:
4238 case LY_STMT_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004239 CHECK_ORDER(Y_MOD_META);
4240 break;
4241
4242 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004243 case LY_STMT_REVISION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004244 CHECK_ORDER(Y_MOD_REVISION);
4245 break;
4246 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004247 case LY_STMT_ANYDATA:
4248 case LY_STMT_ANYXML:
4249 case LY_STMT_AUGMENT:
4250 case LY_STMT_CHOICE:
4251 case LY_STMT_CONTAINER:
4252 case LY_STMT_DEVIATION:
4253 case LY_STMT_EXTENSION:
4254 case LY_STMT_FEATURE:
4255 case LY_STMT_GROUPING:
4256 case LY_STMT_IDENTITY:
4257 case LY_STMT_LEAF:
4258 case LY_STMT_LEAF_LIST:
4259 case LY_STMT_LIST:
4260 case LY_STMT_NOTIFICATION:
4261 case LY_STMT_RPC:
4262 case LY_STMT_TYPEDEF:
4263 case LY_STMT_USES:
4264 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004265 mod_stmt = Y_MOD_BODY;
4266 break;
4267 default:
4268 /* error handled in the next switch */
4269 break;
4270 }
4271#undef CHECK_ORDER
4272
4273 prev_kw = kw;
4274 switch (kw) {
4275 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004276 case LY_STMT_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004277 LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
4278 ctx->mod_version = submod->version;
4279 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004280 case LY_STMT_BELONGS_TO:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004281 LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
4282 break;
4283
4284 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004285 case LY_STMT_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004286 LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
4287 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004288 case LY_STMT_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004289 LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
4290 break;
4291
4292 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004293 case LY_STMT_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004294 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
4295 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004296 case LY_STMT_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004297 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
4298 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004299 case LY_STMT_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004300 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
4301 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004302 case LY_STMT_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004303 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
4304 break;
4305
4306 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004307 case LY_STMT_REVISION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004308 LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
4309 break;
4310
4311 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004312 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02004313 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004314 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02004315 case LY_STMT_ANYXML:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004316 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
4317 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004318 case LY_STMT_CHOICE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004319 LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
4320 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004321 case LY_STMT_CONTAINER:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004322 LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
4323 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004324 case LY_STMT_LEAF:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004325 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
4326 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004327 case LY_STMT_LEAF_LIST:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004328 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
4329 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004330 case LY_STMT_LIST:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004331 LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
4332 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004333 case LY_STMT_USES:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004334 LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
4335 break;
4336
Radek Krejcid6b76452019-09-03 17:03:03 +02004337 case LY_STMT_AUGMENT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004338 LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
4339 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004340 case LY_STMT_DEVIATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004341 LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
4342 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004343 case LY_STMT_EXTENSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004344 LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
4345 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004346 case LY_STMT_FEATURE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004347 LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
4348 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004349 case LY_STMT_GROUPING:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004350 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
4351 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004352 case LY_STMT_IDENTITY:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004353 LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
4354 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004355 case LY_STMT_NOTIFICATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004356 LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
4357 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004358 case LY_STMT_RPC:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004359 LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
4360 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004361 case LY_STMT_TYPEDEF:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004362 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
4363 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004364 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004365 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
4366 break;
4367
4368 default:
David Sedlákb3077192019-06-19 10:55:37 +02004369 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004370 return LY_EVALID;
4371 }
4372 }
4373 LY_CHECK_RET(ret);
4374
4375checks:
4376 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02004377 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004378
4379 /* mandatory substatements */
4380 if (!submod->belongsto) {
David Sedlákb3077192019-06-19 10:55:37 +02004381 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004382 return LY_EVALID;
4383 }
4384
4385 /* submodules share the namespace with the module names, so there must not be
4386 * a submodule of the same name in the context, no need for revision matching */
4387 dup = ly_ctx_get_submodule(ctx->ctx, NULL, submod->name, NULL);
4388 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
David Sedlákb3077192019-06-19 10:55:37 +02004389 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004390 return LY_EVALID;
4391 }
4392
Michal Vasko7fbc8162018-09-17 10:35:16 +02004393 return ret;
4394}
4395
Radek Krejcid4557c62018-09-17 11:42:09 +02004396LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02004397yang_parse_submodule(struct lys_parser_ctx **context, struct ly_ctx *ly_ctx, struct lys_parser_ctx *main_ctx, const char *data, struct lysp_submodule **submod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004398{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004399 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004400 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004401 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004402 enum ly_stmt kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004403 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004404
David Sedlák1b623122019-08-05 15:27:49 +02004405 /* create context */
4406 *context = calloc(1, sizeof **context);
4407 LY_CHECK_ERR_RET(!(*context), LOGMEM(ly_ctx), LY_EMEM);
4408 (*context)->ctx = ly_ctx;
Radek Krejci99435242019-09-05 16:19:15 +02004409 (*context)->pos_type = LY_VLOG_LINE;
David Sedlák1b623122019-08-05 15:27:49 +02004410 (*context)->line = 1;
4411
4412 /* map the typedefs and groupings list from main context to the submodule's context */
4413 memcpy(&(*context)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
4414 memcpy(&(*context)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
4415
Michal Vasko7fbc8162018-09-17 10:35:16 +02004416 /* "module"/"submodule" */
David Sedlák1b623122019-08-05 15:27:49 +02004417 ret = get_keyword(*context, &data, &kw, &word, &word_len);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004418 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004419
Radek Krejcid6b76452019-09-03 17:03:03 +02004420 if (kw == LY_STMT_MODULE) {
David Sedlák1b623122019-08-05 15:27:49 +02004421 LOGERR((*context)->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004422 ret = LY_EINVAL;
4423 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02004424 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02004425 LOGVAL_PARSER(*context, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004426 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004427 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004428 }
4429
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004430 mod_p = calloc(1, sizeof *mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02004431 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM((*context)->ctx), cleanup);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004432 mod_p->parsing = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004433
4434 /* substatements */
David Sedlák1b623122019-08-05 15:27:49 +02004435 ret = parse_submodule(*context, &data, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004436 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004437
4438 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004439 while(*data && isspace(*data)) {
4440 data++;
4441 }
4442 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02004443 LOGVAL_PARSER(*context, LY_VCODE_TRAILING_SUBMOD, 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004444 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004445 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004446 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004447
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004448 mod_p->parsing = 0;
4449 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004450
Radek Krejcibbe09a92018-11-08 09:36:54 +01004451cleanup:
4452 if (ret) {
David Sedlák1b623122019-08-05 15:27:49 +02004453 lysp_submodule_free((*context)->ctx, mod_p);
4454 lys_parser_ctx_free(*context);
4455 *context = NULL;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004456 }
4457
4458 return ret;
4459}
4460
4461LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02004462yang_parse_module(struct lys_parser_ctx **context, const char *data, struct lys_module *mod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004463{
4464 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004465 char *word;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004466 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004467 enum ly_stmt kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004468 struct lysp_module *mod_p = NULL;
4469
David Sedlák1b623122019-08-05 15:27:49 +02004470 /* create context */
4471 *context = calloc(1, sizeof **context);
4472 LY_CHECK_ERR_RET(!(*context), LOGMEM(mod->ctx), LY_EMEM);
4473 (*context)->ctx = mod->ctx;
Radek Krejci335332a2019-09-05 13:03:35 +02004474 (*context)->pos_type = LY_VLOG_LINE;
David Sedlák1b623122019-08-05 15:27:49 +02004475 (*context)->line = 1;
4476
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004477 /* "module"/"submodule" */
David Sedlák1b623122019-08-05 15:27:49 +02004478 ret = get_keyword(*context, &data, &kw, &word, &word_len);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004479 LY_CHECK_GOTO(ret, cleanup);
4480
Radek Krejcid6b76452019-09-03 17:03:03 +02004481 if (kw == LY_STMT_SUBMODULE) {
David Sedlák1b623122019-08-05 15:27:49 +02004482 LOGERR((*context)->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004483 ret = LY_EINVAL;
4484 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02004485 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02004486 LOGVAL_PARSER((*context), LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004487 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004488 goto cleanup;
4489 }
4490
4491 mod_p = calloc(1, sizeof *mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02004492 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM((*context)->ctx), cleanup);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004493 mod_p->mod = mod;
4494 mod_p->parsing = 1;
4495
4496 /* substatements */
David Sedlák1b623122019-08-05 15:27:49 +02004497 ret = parse_module(*context, &data, mod_p);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004498 LY_CHECK_GOTO(ret, cleanup);
4499
4500 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004501 while(*data && isspace(*data)) {
4502 data++;
4503 }
4504 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02004505 LOGVAL_PARSER(*context, LY_VCODE_TRAILING_MOD, 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004506 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004507 goto cleanup;
4508 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004509
4510 mod_p->parsing = 0;
4511 mod->parsed = mod_p;
4512
4513cleanup:
4514 if (ret) {
4515 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02004516 lys_parser_ctx_free(*context);
4517 *context = NULL;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004518 }
4519
Michal Vasko7fbc8162018-09-17 10:35:16 +02004520 return ret;
4521}