blob: ca713b97cdaf76ae183286c3d02fb7783f2318ee [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";
fredgand49fe112019-10-21 20:51:50 +0800404 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200405 break;
406 case 't':
407 c = "\t";
fredgand49fe112019-10-21 20:51:50 +0800408 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200409 break;
410 case '\"':
411 c = *data;
412 break;
413 case '\\':
414 c = *data;
415 break;
416 default:
David Sedlákb3077192019-06-19 10:55:37 +0200417 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200418 return LY_EVALID;
419 }
420
421 /* check and store character */
David Sedlák40bb13b2019-07-10 14:34:18 +0200422 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 +0200423
424 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200425 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200426 break;
427 case 4:
428 switch (**data) {
429 case '+':
430 /* string continues */
431 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200432 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200433 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200434 case '\n':
435 ++ctx->line;
436 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200437 case ' ':
438 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200439 /* just skip */
440 break;
441 default:
442 /* string is finished */
443 goto string_end;
444 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200445 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200446 break;
447 case 5:
448 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200449 case '\n':
450 ++ctx->line;
451 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200452 case ' ':
453 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200454 /* skip */
455 break;
456 case '\'':
457 string = 1;
458 break;
459 case '\"':
460 string = 2;
461 break;
462 default:
463 /* it must be quoted again */
David Sedlákb3077192019-06-19 10:55:37 +0200464 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200465 return LY_EVALID;
466 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200467 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200468 break;
469 default:
470 return LY_EINT;
471 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200472 }
473
474string_end:
Radek Krejci4e199f52019-05-28 09:09:28 +0200475 if (arg <= Y_PREF_IDENTIF_ARG && !(*word_len)) {
476 /* empty identifier */
David Sedlákb3077192019-06-19 10:55:37 +0200477 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Statement argument is required.");
Radek Krejci4e199f52019-05-28 09:09:28 +0200478 return LY_EVALID;
479 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200480 return LY_SUCCESS;
481}
482
Michal Vaskoea5abea2018-09-18 13:10:54 +0200483/**
484 * @brief Get another YANG string from the raw data.
485 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200486 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200487 * @param[in,out] data Data to read from, always moved to currently handled character.
488 * @param[in] arg Type of YANG keyword argument expected.
Radek Krejcid3ca0632019-04-16 16:54:54 +0200489 * @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 +0200490 * @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 +0200491 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
492 * set to NULL. Otherwise equal to \p word_p.
493 * @param[out] word_len Length of the read string.
494 *
495 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200496 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200497LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200498get_argument(struct lys_parser_ctx *ctx, const char **data, enum yang_arg arg,
Radek Krejcid3ca0632019-04-16 16:54:54 +0200499 uint16_t *flags, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200500{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200501 size_t buf_len = 0;
David Sedlák40bb13b2019-07-10 14:34:18 +0200502 int prefix = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200503 /* word buffer - dynamically allocated */
504 *word_b = NULL;
505
506 /* word pointer - just a pointer to data */
507 *word_p = NULL;
508
509 *word_len = 0;
510 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200511 switch (**data) {
512 case '\'':
513 case '\"':
514 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200515 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
David Sedlákb3077192019-06-19 10:55:37 +0200516 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data,
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200517 "unquoted string character, optsep, semicolon or opening brace");
518 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200519 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200520 if (flags) {
521 (*flags) |= (**data) == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
522 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100523 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200524 goto str_end;
525 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200526 if ((*data)[1] == '/') {
527 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200528 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100529 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200530 } else if ((*data)[1] == '*') {
531 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200532 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100533 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200534 } else {
535 /* not a comment after all */
David Sedlák40bb13b2019-07-10 14:34:18 +0200536 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 +0200537 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200538 break;
539 case ' ':
540 if (*word_len) {
541 /* word is finished */
542 goto str_end;
543 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200544 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200545 break;
546 case '\t':
547 if (*word_len) {
548 /* word is finished */
549 goto str_end;
550 }
551 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200552 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200553
554 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200555 break;
556 case '\n':
557 if (*word_len) {
558 /* word is finished */
559 goto str_end;
560 }
561 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200562 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200563
564 /* track line numbers */
565 ++ctx->line;
566
567 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200568 break;
569 case ';':
570 case '{':
571 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
572 /* word is finished */
573 goto str_end;
574 }
575
David Sedlákb3077192019-06-19 10:55:37 +0200576 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200577 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200578 case '}':
579 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
David Sedlákb3077192019-06-19 10:55:37 +0200580 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data,
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200581 "unquoted string character, optsep, semicolon or opening brace");
582 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200583 default:
David Sedlák40bb13b2019-07-10 14:34:18 +0200584 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 +0200585 break;
586 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200587 }
588
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200589 /* unexpected end of loop */
David Sedlákb3077192019-06-19 10:55:37 +0200590 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200591 return LY_EVALID;
592
Michal Vasko7fbc8162018-09-17 10:35:16 +0200593str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200594 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200595 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200596 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
597 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
598 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200599 *word_p = *word_b;
600 }
601
602 return LY_SUCCESS;
603}
604
Michal Vaskoea5abea2018-09-18 13:10:54 +0200605/**
606 * @brief Get another YANG keyword from the raw data.
607 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200608 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200609 * @param[in,out] data Data to read from, always moved to currently handled character.
610 * @param[out] kw YANG keyword read.
611 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
612 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
613 *
614 * @return LY_ERR values.
615 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +0200616LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +0200617get_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 +0200618{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200619 int prefix;
620 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200621 unsigned int c;
622 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200623
624 if (word_p) {
625 *word_p = NULL;
626 *word_len = 0;
627 }
628
629 /* first skip "optsep", comments */
630 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200631 switch (**data) {
632 case '/':
633 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200634 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200635 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100636 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200637 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200638 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200639 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100640 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200641 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200642 /* error - not a comment after all, keyword cannot start with slash */
David Sedlákb3077192019-06-19 10:55:37 +0200643 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
Radek Krejcidcc7b322018-10-11 14:24:02 +0200644 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200645 }
Radek Krejci13028282019-06-11 14:56:48 +0200646 continue;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200647 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200648 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200649 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200650 ctx->indent = 0;
651 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200652 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200653 /* skip whitespaces (optsep) */
654 ++ctx->indent;
655 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200656 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200657 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200658 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200659 break;
660 default:
661 /* either a keyword start or an invalid character */
662 goto keyword_start;
663 }
664
665 ++(*data);
666 }
667
668keyword_start:
669 word_start = *data;
David Sedlák5f8f0332019-06-18 16:34:30 +0200670 *kw = lysp_match_kw(ctx, data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200671
Radek Krejcid6b76452019-09-03 17:03:03 +0200672 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 +0200673 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200674 }
675
Radek Krejcid6b76452019-09-03 17:03:03 +0200676 if (*kw != LY_STMT_NONE) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200677 /* make sure we have the whole keyword */
678 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200679 case '\n':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200680 case '\t':
Radek Krejciabdd8062019-06-11 16:44:19 +0200681 case ' ':
682 /* mandatory "sep" is just checked, not eaten so nothing in the context is updated */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200683 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200684 case ':':
685 /* keyword is not actually a keyword, but prefix of an extension.
686 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
687 * and we will be checking the keyword (extension instance) itself */
688 prefix = 1;
689 MOVE_INPUT(ctx, data, 1);
690 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200691 case '{':
692 /* allowed only for input and output statements which can be without arguments */
Radek Krejcid6b76452019-09-03 17:03:03 +0200693 if (*kw == LY_STMT_INPUT || *kw == LY_STMT_OUTPUT) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200694 break;
695 }
696 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200697 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200698 MOVE_INPUT(ctx, data, 1);
David Sedlákb3077192019-06-19 10:55:37 +0200699 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
Radek Krejci44ceedc2018-10-02 15:54:31 +0200700 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200701 return LY_EVALID;
702 }
703 } else {
704 /* still can be an extension */
705 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200706extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200707 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200708 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
David Sedlákb3077192019-06-19 10:55:37 +0200709 LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200710 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200711 /* check character validity */
David Sedlák4a650532019-07-10 11:55:18 +0200712 LY_CHECK_RET(lysp_check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200713 }
714 if (!**data) {
David Sedlákb3077192019-06-19 10:55:37 +0200715 LOGVAL_PARSER(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200716 return LY_EVALID;
717 }
718
719 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200720 if (prefix != 2) {
David Sedlákb3077192019-06-19 10:55:37 +0200721 LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200722 return LY_EVALID;
723 }
724
Radek Krejcid6b76452019-09-03 17:03:03 +0200725 *kw = LY_STMT_EXTENSION_INSTANCE;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200726 }
Radek Krejci626df482018-10-11 15:06:31 +0200727success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200728 if (word_p) {
729 *word_p = (char *)word_start;
730 *word_len = *data - word_start;
731 }
732
733 return LY_SUCCESS;
734}
735
Michal Vaskoea5abea2018-09-18 13:10:54 +0200736/**
737 * @brief Parse extension instance substatements.
738 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200739 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200740 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci335332a2019-09-05 13:03:35 +0200741 * @param[in] kw Statement keyword value matching @p word value.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200742 * @param[in] word Extension instance substatement name (keyword).
743 * @param[in] word_len Extension instance substatement name length.
744 * @param[in,out] child Children of this extension instance to add to.
745 *
746 * @return LY_ERR values.
747 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200748static LY_ERR
Radek Krejci335332a2019-09-05 13:03:35 +0200749parse_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 +0200750 struct lysp_stmt **child)
751{
752 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100753 LY_ERR ret = LY_SUCCESS;
Radek Krejci335332a2019-09-05 13:03:35 +0200754 enum ly_stmt child_kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200755 struct lysp_stmt *stmt, *par_child;
756
757 stmt = calloc(1, sizeof *stmt);
758 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
759
Radek Krejcibb9b1982019-04-08 14:24:59 +0200760 /* insert into parent statements */
761 if (!*child) {
762 *child = stmt;
763 } else {
764 for (par_child = *child; par_child->next; par_child = par_child->next);
765 par_child->next = stmt;
766 }
767
Radek Krejci44ceedc2018-10-02 15:54:31 +0200768 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci335332a2019-09-05 13:03:35 +0200769 stmt->kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200770
771 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200772 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200773
Radek Krejci0ae092d2018-09-20 16:43:19 +0200774 if (word) {
775 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200776 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200777 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200778 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200779 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200780 }
781
Radek Krejci335332a2019-09-05 13:03:35 +0200782 YANG_READ_SUBSTMT_FOR(ctx, data, child_kw, word, word_len, ret, ) {
783 LY_CHECK_RET(parse_ext_substmt(ctx, data, child_kw, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200784 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200785 return ret;
786}
787
Michal Vaskoea5abea2018-09-18 13:10:54 +0200788/**
789 * @brief Parse extension instance.
790 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200791 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200792 * @param[in,out] data Data to read from, always moved to currently handled character.
793 * @param[in] ext_name Extension instance substatement name (keyword).
794 * @param[in] ext_name_len Extension instance substatement name length.
795 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
796 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
797 * @param[in,out] exts Extension instances to add to.
798 *
799 * @return LY_ERR values.
800 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200801static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200802parse_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 +0200803 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
804{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100805 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200806 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200807 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200808 struct lysp_ext_instance *e;
Radek Krejcid6b76452019-09-03 17:03:03 +0200809 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200810
Radek Krejci2c4e7172018-10-19 15:56:26 +0200811 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200812
813 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200814 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200815 e->insubstmt = insubstmt;
816 e->insubstmt_index = insubstmt_index;
817
818 /* get optional argument */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200819 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200820
Radek Krejci0ae092d2018-09-20 16:43:19 +0200821 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200822 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200823 }
824
Radek Krejci6d6556c2018-11-08 09:37:45 +0100825 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci335332a2019-09-05 13:03:35 +0200826 LY_CHECK_RET(parse_ext_substmt(ctx, data, kw, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200827 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200828 return ret;
829}
830
Michal Vaskoea5abea2018-09-18 13:10:54 +0200831/**
832 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
833 * description, etc...
834 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200835 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200836 * @param[in,out] data Data to read from, always moved to currently handled character.
837 * @param[in] substmt Type of this substatement.
838 * @param[in] substmt_index Index of this substatement.
839 * @param[in,out] value Place to store the parsed value.
840 * @param[in] arg Type of the YANG keyword argument (of the value).
841 * @param[in,out] exts Extension instances to add to.
842 *
843 * @return LY_ERR values.
844 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200845static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200846parse_text_field(struct lys_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200847 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
848{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100849 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200850 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200851 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200852 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200853
854 if (*value) {
David Sedlákb3077192019-06-19 10:55:37 +0200855 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200856 return LY_EVALID;
857 }
858
859 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200860 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200861
862 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200863 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200864
Radek Krejci6d6556c2018-11-08 09:37:45 +0100865 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200866 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200867 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100868 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200869 break;
870 default:
David Sedlákb3077192019-06-19 10:55:37 +0200871 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200872 return LY_EVALID;
873 }
874 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200875 return ret;
876}
877
Michal Vaskoea5abea2018-09-18 13:10:54 +0200878/**
879 * @brief Parse the yang-version statement.
880 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200881 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200882 * @param[in,out] data Data to read from, always moved to currently handled character.
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100883 * @param[out] version Storage for the parsed information.
884 * @param[in, out] exts Extension instances to add to.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200885 *
886 * @return LY_ERR values.
887 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200888static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200889parse_yangversion(struct lys_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200890{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100891 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200892 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200893 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200894 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200895
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100896 if (*version) {
David Sedlákb3077192019-06-19 10:55:37 +0200897 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200898 return LY_EVALID;
899 }
900
901 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200902 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200903
904 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100905 *version = LYS_VERSION_1_0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200906 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100907 *version = LYS_VERSION_1_1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200908 } else {
David Sedlákb3077192019-06-19 10:55:37 +0200909 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200910 free(buf);
911 return LY_EVALID;
912 }
913 free(buf);
914
Radek Krejci6d6556c2018-11-08 09:37:45 +0100915 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200916 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200917 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +0100918 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200919 break;
920 default:
David Sedlákb3077192019-06-19 10:55:37 +0200921 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200922 return LY_EVALID;
923 }
924 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200925 return ret;
926}
927
Michal Vaskoea5abea2018-09-18 13:10:54 +0200928/**
929 * @brief Parse the belongs-to statement.
930 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200931 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200932 * @param[in,out] data Data to read from, always moved to currently handled character.
933 * @param[in,out] belongsto Place to store the parsed value.
934 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
935 * @param[in,out] exts Extension instances to add to.
936 *
937 * @return LY_ERR values.
938 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200939static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200940parse_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 +0200941{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100942 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200943 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200944 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200945 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200946
947 if (*belongsto) {
David Sedlákb3077192019-06-19 10:55:37 +0200948 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200949 return LY_EVALID;
950 }
951
952 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200953 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200954
Radek Krejci44ceedc2018-10-02 15:54:31 +0200955 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejcif09e4e82019-06-14 15:08:11 +0200956
Radek Krejci6d6556c2018-11-08 09:37:45 +0100957 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200958 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200959 case LY_STMT_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100960 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200961 break;
Radek Krejcid6b76452019-09-03 17:03:03 +0200962 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100963 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200964 break;
965 default:
David Sedlákb3077192019-06-19 10:55:37 +0200966 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200967 return LY_EVALID;
968 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200969 }
Radek Krejcic59bc972018-09-17 16:13:06 +0200970 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +0100971checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200972 /* mandatory substatements */
973 if (!*prefix) {
David Sedlákb3077192019-06-19 10:55:37 +0200974 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200975 return LY_EVALID;
976 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200977 return ret;
978}
979
Michal Vaskoea5abea2018-09-18 13:10:54 +0200980/**
981 * @brief Parse the revision-date statement.
982 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200983 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200984 * @param[in,out] data Data to read from, always moved to currently handled character.
985 * @param[in,out] rev Array to store the parsed value in.
986 * @param[in,out] exts Extension instances to add to.
987 *
988 * @return LY_ERR values.
989 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200990static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +0200991parse_revisiondate(struct lys_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200992{
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100993 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200994 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +0200995 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +0200996 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200997
998 if (rev[0]) {
David Sedlákb3077192019-06-19 10:55:37 +0200999 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001000 return LY_EVALID;
1001 }
1002
1003 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001004 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001005
1006 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001007 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001008 free(buf);
1009 return LY_EVALID;
1010 }
1011
1012 /* store value and spend buf if allocated */
1013 strncpy(rev, word, word_len);
1014 free(buf);
1015
Radek Krejci6d6556c2018-11-08 09:37:45 +01001016 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001017 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001018 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001019 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001020 break;
1021 default:
David Sedlákb3077192019-06-19 10:55:37 +02001022 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001023 return LY_EVALID;
1024 }
1025 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001026 return ret;
1027}
1028
Michal Vaskoea5abea2018-09-18 13:10:54 +02001029/**
1030 * @brief Parse the include statement.
1031 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001032 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001033 * @param[in] module_name Name of the module to check name collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001034 * @param[in,out] data Data to read from, always moved to currently handled character.
1035 * @param[in,out] includes Parsed includes to add to.
1036 *
1037 * @return LY_ERR values.
1038 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001039static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001040parse_include(struct lys_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001041{
Radek Krejcid33273d2018-10-25 14:55:52 +02001042 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001043 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001044 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001045 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001046 struct lysp_include *inc;
1047
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001048 LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001049
1050 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001051 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001052
Radek Krejci086c7132018-10-26 15:29:04 +02001053 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1054
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001055 /* submodules share the namespace with the module names, so there must not be
1056 * a module of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001057 if (!strcmp(module_name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
David Sedlákb3077192019-06-19 10:55:37 +02001058 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001059 return LY_EVALID;
1060 }
1061
Radek Krejci6d6556c2018-11-08 09:37:45 +01001062 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001063 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001064 case LY_STMT_DESCRIPTION:
Radek Krejci335332a2019-09-05 13:03:35 +02001065 PARSER_CHECK_STMTVER2_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001066 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 +02001067 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001068 case LY_STMT_REFERENCE:
Radek Krejci335332a2019-09-05 13:03:35 +02001069 PARSER_CHECK_STMTVER2_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001070 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 +02001071 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001072 case LY_STMT_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001073 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001074 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001075 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001076 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001077 break;
1078 default:
David Sedlákb3077192019-06-19 10:55:37 +02001079 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001080 return LY_EVALID;
1081 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001082 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001083 return ret;
1084}
1085
Michal Vaskoea5abea2018-09-18 13:10:54 +02001086/**
1087 * @brief Parse the import statement.
1088 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001089 * @param[in] ctx yang parser context for logging.
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001090 * @param[in] module_prefix Prefix of the module to check prefix collisions.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001091 * @param[in,out] data Data to read from, always moved to currently handled character.
1092 * @param[in,out] imports Parsed imports to add to.
1093 *
1094 * @return LY_ERR values.
1095 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001096static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001097parse_import(struct lys_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001098{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001099 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001100 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001101 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001102 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001103 struct lysp_import *imp;
1104
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001105 LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001106
1107 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001108 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001109 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001110
Radek Krejci6d6556c2018-11-08 09:37:45 +01001111 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001112 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001113 case LY_STMT_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001114 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 +01001115 LY_CHECK_RET(lysp_check_prefix(ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001116 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001117 case LY_STMT_DESCRIPTION:
Radek Krejci335332a2019-09-05 13:03:35 +02001118 PARSER_CHECK_STMTVER2_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001119 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 +02001120 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001121 case LY_STMT_REFERENCE:
Radek Krejci335332a2019-09-05 13:03:35 +02001122 PARSER_CHECK_STMTVER2_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001123 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 +02001124 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001125 case LY_STMT_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001126 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001127 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001128 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001129 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001130 break;
1131 default:
David Sedlákb3077192019-06-19 10:55:37 +02001132 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001133 return LY_EVALID;
1134 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001135 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001136 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001137checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001138 /* mandatory substatements */
David Sedlákb3077192019-06-19 10:55:37 +02001139 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001140
1141 return ret;
1142}
1143
Michal Vaskoea5abea2018-09-18 13:10:54 +02001144/**
1145 * @brief Parse the revision statement.
1146 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001147 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001148 * @param[in,out] data Data to read from, always moved to currently handled character.
1149 * @param[in,out] revs Parsed revisions to add to.
1150 *
1151 * @return LY_ERR values.
1152 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001153static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001154parse_revision(struct lys_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001155{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001156 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001157 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001158 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001159 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001160 struct lysp_revision *rev;
1161
Radek Krejci2c4e7172018-10-19 15:56:26 +02001162 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001163
1164 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001165 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001166
1167 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001168 if (lysp_check_date(ctx, word, word_len, "revision")) {
David Sedlák68ef3dc2019-07-22 13:40:19 +02001169 free(buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001170 return LY_EVALID;
1171 }
1172
Radek Krejcib7db73a2018-10-24 14:18:40 +02001173 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001174 free(buf);
1175
Radek Krejci6d6556c2018-11-08 09:37:45 +01001176 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001177 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001178 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001179 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 +02001180 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001181 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001182 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 +02001183 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001184 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001185 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001186 break;
1187 default:
David Sedlákb3077192019-06-19 10:55:37 +02001188 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189 return LY_EVALID;
1190 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001191 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001192 return ret;
1193}
1194
Michal Vaskoea5abea2018-09-18 13:10:54 +02001195/**
1196 * @brief Parse a generic text field that can have more instances such as base.
1197 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001198 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001199 * @param[in,out] data Data to read from, always moved to currently handled character.
1200 * @param[in] substmt Type of this substatement.
1201 * @param[in,out] texts Parsed values to add to.
1202 * @param[in] arg Type of the expected argument.
1203 * @param[in,out] exts Extension instances to add to.
1204 *
1205 * @return LY_ERR values.
1206 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001207static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001208parse_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 +02001209 struct lysp_ext_instance **exts)
1210{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001211 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001212 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001213 const char **item;
1214 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001215 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001216
1217 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001218 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001219
1220 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001221 LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001222
Radek Krejci151a5b72018-10-19 14:21:44 +02001223 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001224 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001225 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001226 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001227 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001228 break;
1229 default:
David Sedlákb3077192019-06-19 10:55:37 +02001230 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001231 return LY_EVALID;
1232 }
1233 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001234 return ret;
1235}
1236
Michal Vaskoea5abea2018-09-18 13:10:54 +02001237/**
1238 * @brief Parse the config statement.
1239 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001240 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001241 * @param[in,out] data Data to read from, always moved to currently handled character.
1242 * @param[in,out] flags Flags to add to.
1243 * @param[in,out] exts Extension instances to add to.
1244 *
1245 * @return LY_ERR values.
1246 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001247static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001248parse_config(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001249{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001250 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001251 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001252 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001253 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001254
1255 if (*flags & LYS_CONFIG_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001256 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001257 return LY_EVALID;
1258 }
1259
1260 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001261 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001262
1263 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1264 *flags |= LYS_CONFIG_W;
1265 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1266 *flags |= LYS_CONFIG_R;
1267 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001268 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001269 free(buf);
1270 return LY_EVALID;
1271 }
1272 free(buf);
1273
Radek Krejci6d6556c2018-11-08 09:37:45 +01001274 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001275 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001276 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001277 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001278 break;
1279 default:
David Sedlákb3077192019-06-19 10:55:37 +02001280 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001281 return LY_EVALID;
1282 }
1283 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001284 return ret;
1285}
1286
Michal Vaskoea5abea2018-09-18 13:10:54 +02001287/**
1288 * @brief Parse the mandatory statement.
1289 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001290 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001291 * @param[in,out] data Data to read from, always moved to currently handled character.
1292 * @param[in,out] flags Flags to add to.
1293 * @param[in,out] exts Extension instances to add to.
1294 *
1295 * @return LY_ERR values.
1296 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001297static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001298parse_mandatory(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001299{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001300 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001301 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001302 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001303 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001304
1305 if (*flags & LYS_MAND_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001306 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001307 return LY_EVALID;
1308 }
1309
1310 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001311 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001312
1313 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1314 *flags |= LYS_MAND_TRUE;
1315 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1316 *flags |= LYS_MAND_FALSE;
1317 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001318 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001319 free(buf);
1320 return LY_EVALID;
1321 }
1322 free(buf);
1323
Radek Krejci6d6556c2018-11-08 09:37:45 +01001324 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001325 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001326 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001327 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001328 break;
1329 default:
David Sedlákb3077192019-06-19 10:55:37 +02001330 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001331 return LY_EVALID;
1332 }
1333 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001334 return ret;
1335}
1336
Michal Vaskoea5abea2018-09-18 13:10:54 +02001337/**
1338 * @brief Parse a restriction such as range or length.
1339 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001340 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001341 * @param[in,out] data Data to read from, always moved to currently handled character.
1342 * @param[in] restr_kw Type of this particular restriction.
1343 * @param[in,out] exts Extension instances to add to.
1344 *
1345 * @return LY_ERR values.
1346 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001347static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02001348parse_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 +02001349{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001350 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001351 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001352 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001353 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001354
1355 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001356 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001357
David Sedlákb9b892c2019-07-12 14:44:02 +02001358 YANG_CHECK_NONEMPTY(ctx, word_len, ly_stmt2str(restr_kw));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001359 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001360 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001361 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001362 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001363 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 +02001364 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001365 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001366 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 +02001367 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001368 case LY_STMT_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001369 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 +02001370 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001371 case LY_STMT_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001372 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 +02001373 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001374 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001375 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001376 break;
1377 default:
David Sedlákb3077192019-06-19 10:55:37 +02001378 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001379 return LY_EVALID;
1380 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001381 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001382 return ret;
1383}
1384
Michal Vaskoea5abea2018-09-18 13:10:54 +02001385/**
1386 * @brief Parse a restriction that can have more instances such as must.
1387 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001388 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001389 * @param[in,out] data Data to read from, always moved to currently handled character.
1390 * @param[in] restr_kw Type of this particular restriction.
1391 * @param[in,out] restrs Restrictions to add to.
1392 *
1393 * @return LY_ERR values.
1394 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001395static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02001396parse_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 +02001397{
1398 struct lysp_restr *restr;
1399
Radek Krejci2c4e7172018-10-19 15:56:26 +02001400 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001401 return parse_restr(ctx, data, restr_kw, restr);
1402}
1403
Michal Vaskoea5abea2018-09-18 13:10:54 +02001404/**
1405 * @brief Parse the status statement.
1406 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001407 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001408 * @param[in,out] data Data to read from, always moved to currently handled character.
1409 * @param[in,out] flags Flags to add to.
1410 * @param[in,out] exts Extension instances to add to.
1411 *
1412 * @return LY_ERR values.
1413 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001414static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001415parse_status(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001416{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001417 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001418 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001419 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001420 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001421
1422 if (*flags & LYS_STATUS_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02001423 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001424 return LY_EVALID;
1425 }
1426
1427 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001428 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001429
1430 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1431 *flags |= LYS_STATUS_CURR;
1432 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1433 *flags |= LYS_STATUS_DEPRC;
1434 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1435 *flags |= LYS_STATUS_OBSLT;
1436 } else {
David Sedlákb3077192019-06-19 10:55:37 +02001437 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438 free(buf);
1439 return LY_EVALID;
1440 }
1441 free(buf);
1442
Radek Krejci6d6556c2018-11-08 09:37:45 +01001443 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001444 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001445 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001446 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001447 break;
1448 default:
David Sedlákb3077192019-06-19 10:55:37 +02001449 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001450 return LY_EVALID;
1451 }
1452 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001453 return ret;
1454}
1455
Michal Vaskoea5abea2018-09-18 13:10:54 +02001456/**
1457 * @brief Parse the when statement.
1458 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001459 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001460 * @param[in,out] data Data to read from, always moved to currently handled character.
1461 * @param[in,out] when_p When pointer to parse to.
1462 *
1463 * @return LY_ERR values.
1464 */
Radek Krejcif09e4e82019-06-14 15:08:11 +02001465LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001466parse_when(struct lys_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001467{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001468 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001469 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001470 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001471 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001472 struct lysp_when *when;
1473
1474 if (*when_p) {
David Sedlákb3077192019-06-19 10:55:37 +02001475 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001476 return LY_EVALID;
1477 }
1478
1479 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001480 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001481
1482 /* get value */
Radek Krejci2f54df52019-06-21 10:59:19 +02001483 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 +02001484 YANG_CHECK_NONEMPTY(ctx, word_len, "when");
Radek Krejci44ceedc2018-10-02 15:54:31 +02001485 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001486
Radek Krejcif09e4e82019-06-14 15:08:11 +02001487 *when_p = when;
1488
Radek Krejci6d6556c2018-11-08 09:37:45 +01001489 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001490 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001491 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001492 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 +02001493 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001494 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001495 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 +02001496 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001497 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001498 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001499 break;
1500 default:
David Sedlákb3077192019-06-19 10:55:37 +02001501 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001502 return LY_EVALID;
1503 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001504 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001505 return ret;
1506}
1507
Michal Vaskoea5abea2018-09-18 13:10:54 +02001508/**
1509 * @brief Parse the anydata or anyxml statement.
1510 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001511 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001512 * @param[in,out] data Data to read from, always moved to currently handled character.
1513 * @param[in] kw Type of this particular keyword.
1514 * @param[in,out] siblings Siblings to add to.
1515 *
1516 * @return LY_ERR values.
1517 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02001518LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02001519parse_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 +02001520{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001521 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001522 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001523 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001524 struct lysp_node_anydata *any;
1525
David Sedlák60adc092019-08-06 15:57:02 +02001526 /* create new structure and insert into siblings */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02001527 LY_LIST_NEW_RET(ctx->ctx, siblings, any, next, LY_EMEM);
David Sedlák60adc092019-08-06 15:57:02 +02001528
Radek Krejcid6b76452019-09-03 17:03:03 +02001529 any->nodetype = kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001530 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001531
Michal Vasko7fbc8162018-09-17 10:35:16 +02001532 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001533 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001534 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001535
1536 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001537 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001538 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001539 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001540 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001541 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001542 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001543 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 +02001544 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001545 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001546 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 +02001547 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001548 case LY_STMT_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001549 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001550 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001551 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001552 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001553 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001554 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001555 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 +02001556 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001557 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001558 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001559 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001560 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001561 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001562 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001563 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001564 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001565 break;
1566 default:
David Sedlákb3077192019-06-19 10:55:37 +02001567 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcid6b76452019-09-03 17:03:03 +02001568 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(LY_STMT_ANYDATA) : ly_stmt2str(LY_STMT_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001569 return LY_EVALID;
1570 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001571 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001572 return ret;
1573}
1574
Michal Vaskoea5abea2018-09-18 13:10:54 +02001575/**
1576 * @brief Parse the value or position statement. Substatement of type enum statement.
1577 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001578 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001579 * @param[in,out] data Data to read from, always moved to currently handled character.
1580 * @param[in] val_kw Type of this particular keyword.
1581 * @param[in,out] value Value to write to.
1582 * @param[in,out] flags Flags to write to.
1583 * @param[in,out] exts Extension instances to add to.
1584 *
1585 * @return LY_ERR values.
1586 */
David Sedlákd6ce6d72019-07-16 17:30:18 +02001587LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02001588parse_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 +02001589 struct lysp_ext_instance **exts)
1590{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001591 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001592 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001593 size_t word_len;
Radek Krejci4ad42aa2019-07-23 16:55:58 +02001594 long int num = 0;
1595 unsigned long int unum = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001596 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001597
1598 if (*flags & LYS_SET_VALUE) {
David Sedlákb3077192019-06-19 10:55:37 +02001599 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001600 return LY_EVALID;
1601 }
1602 *flags |= LYS_SET_VALUE;
1603
1604 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001605 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001606
Radek Krejcid6b76452019-09-03 17:03:03 +02001607 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 +02001608 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001609 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001610 }
1611
1612 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001613 if (val_kw == LY_STMT_VALUE) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001614 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001615 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlákb3077192019-06-19 10:55:37 +02001616 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001617 goto error;
1618 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001619 } else {
1620 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001621 if (unum > UINT64_C(4294967295)) {
David Sedlákb3077192019-06-19 10:55:37 +02001622 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001623 goto error;
1624 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001625 }
1626 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001627 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001628 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001629 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001630 }
1631 if (errno == ERANGE) {
David Sedlákb3077192019-06-19 10:55:37 +02001632 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001633 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001634 }
Radek Krejcid6b76452019-09-03 17:03:03 +02001635 if (val_kw == LY_STMT_VALUE) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001636 *value = num;
1637 } else {
1638 *value = unum;
1639 }
1640 free(buf);
1641
Radek Krejci6d6556c2018-11-08 09:37:45 +01001642 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001643 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001644 case LY_STMT_EXTENSION_INSTANCE:
1645 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 +02001646 break;
1647 default:
David Sedlákb3077192019-06-19 10:55:37 +02001648 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001649 return LY_EVALID;
1650 }
1651 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001652 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001653
1654error:
1655 free(buf);
1656 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001657}
1658
Michal Vaskoea5abea2018-09-18 13:10:54 +02001659/**
1660 * @brief Parse the enum or bit statement. Substatement of type statement.
1661 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001662 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001663 * @param[in,out] data Data to read from, always moved to currently handled character.
1664 * @param[in] enum_kw Type of this particular keyword.
1665 * @param[in,out] enums Enums or bits to add to.
1666 *
1667 * @return LY_ERR values.
1668 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001669static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02001670parse_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 +02001671{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001672 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001673 char *buf, *word;
David Sedlák6544c182019-07-12 13:17:33 +02001674 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001675 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001676 struct lysp_type_enum *enm;
1677
Radek Krejci2c4e7172018-10-19 15:56:26 +02001678 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001679
1680 /* get value */
Radek Krejcid6b76452019-09-03 17:03:03 +02001681 LY_CHECK_RET(get_argument(ctx, data, enum_kw == LY_STMT_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
1682 if (enum_kw == LY_STMT_ENUM) {
David Sedlák07869a52019-07-12 14:28:19 +02001683 ret = lysp_check_enum_name(ctx, (const char *)word, word_len);
David Sedlák6544c182019-07-12 13:17:33 +02001684 LY_CHECK_ERR_RET(ret, free(buf), ret);
Radek Krejci335332a2019-09-05 13:03:35 +02001685 } /* else nothing specific for YANG_BIT */
Radek Krejci8b764662018-11-14 14:15:13 +01001686
Radek Krejci44ceedc2018-10-02 15:54:31 +02001687 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Radek Krejci8b764662018-11-14 14:15:13 +01001688 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1689
Radek Krejci6d6556c2018-11-08 09:37:45 +01001690 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001691 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001692 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001693 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 +02001694 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001695 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02001696 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001697 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 +02001698 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001699 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001700 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 +02001701 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001702 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001703 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001704 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001705 case LY_STMT_VALUE:
1706 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 +02001707 ly_stmt2str(enum_kw)), LY_EVALID);
1708 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
1709 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001710 case LY_STMT_POSITION:
1711 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 +02001712 ly_stmt2str(enum_kw)), LY_EVALID);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001713 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001714 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001715 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001716 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001717 break;
1718 default:
David Sedlákb3077192019-06-19 10:55:37 +02001719 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001720 return LY_EVALID;
1721 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001722 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001723 return ret;
1724}
1725
Michal Vaskoea5abea2018-09-18 13:10:54 +02001726/**
1727 * @brief Parse the fraction-digits statement. Substatement of type statement.
1728 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001729 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001730 * @param[in,out] data Data to read from, always moved to currently handled character.
1731 * @param[in,out] fracdig Value to write to.
1732 * @param[in,out] exts Extension instances to add to.
1733 *
1734 * @return LY_ERR values.
1735 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001736static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001737parse_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 +02001738{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001739 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001740 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001741 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001742 unsigned long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02001743 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001744
1745 if (*fracdig) {
David Sedlákb3077192019-06-19 10:55:37 +02001746 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001747 return LY_EVALID;
1748 }
1749
1750 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001751 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001752
1753 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
David Sedlákb3077192019-06-19 10:55:37 +02001754 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001755 free(buf);
1756 return LY_EVALID;
1757 }
1758
1759 errno = 0;
1760 num = strtoul(word, &ptr, 10);
1761 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001762 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02001763 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001764 free(buf);
1765 return LY_EVALID;
1766 }
1767 if ((errno == ERANGE) || (num > 18)) {
David Sedlákb3077192019-06-19 10:55:37 +02001768 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001769 free(buf);
1770 return LY_EVALID;
1771 }
1772 *fracdig = num;
1773 free(buf);
1774
Radek Krejci6d6556c2018-11-08 09:37:45 +01001775 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001776 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001777 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001778 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001779 break;
1780 default:
David Sedlákb3077192019-06-19 10:55:37 +02001781 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001782 return LY_EVALID;
1783 }
1784 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001785 return ret;
1786}
1787
Michal Vaskoea5abea2018-09-18 13:10:54 +02001788/**
1789 * @brief Parse the require-instance statement. Substatement of type statement.
1790 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001791 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001792 * @param[in,out] data Data to read from, always moved to currently handled character.
1793 * @param[in,out] reqinst Value to write to.
1794 * @param[in,out] flags Flags to write to.
1795 * @param[in,out] exts Extension instances to add to.
1796 *
1797 * @return LY_ERR values.
1798 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001799static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001800parse_type_reqinstance(struct lys_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001801 struct lysp_ext_instance **exts)
1802{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001803 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001804 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001805 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001806 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001807
1808 if (*flags & LYS_SET_REQINST) {
David Sedlákb3077192019-06-19 10:55:37 +02001809 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001810 return LY_EVALID;
1811 }
1812 *flags |= LYS_SET_REQINST;
1813
1814 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001815 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001816
1817 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1818 *reqinst = 1;
1819 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02001820 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001821 free(buf);
1822 return LY_EVALID;
1823 }
1824 free(buf);
1825
Radek Krejci6d6556c2018-11-08 09:37:45 +01001826 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001827 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001828 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001829 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001830 break;
1831 default:
David Sedlákb3077192019-06-19 10:55:37 +02001832 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001833 return LY_EVALID;
1834 }
1835 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001836 return ret;
1837}
1838
Michal Vaskoea5abea2018-09-18 13:10:54 +02001839/**
1840 * @brief Parse the modifier statement. Substatement of type pattern statement.
1841 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001842 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001843 * @param[in,out] data Data to read from, always moved to currently handled character.
1844 * @param[in,out] pat Value to write to.
1845 * @param[in,out] exts Extension instances to add to.
1846 *
1847 * @return LY_ERR values.
1848 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001849static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001850parse_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 +02001851{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001852 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001853 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001854 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001855 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001856
1857 if ((*pat)[0] == 0x15) {
David Sedlákb3077192019-06-19 10:55:37 +02001858 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001859 return LY_EVALID;
1860 }
1861
1862 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001863 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001864
1865 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
David Sedlákb3077192019-06-19 10:55:37 +02001866 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001867 free(buf);
1868 return LY_EVALID;
1869 }
1870 free(buf);
1871
1872 /* replace the value in the dictionary */
1873 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001874 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001875 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001876 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001877
1878 assert(buf[0] == 0x06);
1879 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02001880 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001881
Radek Krejci6d6556c2018-11-08 09:37:45 +01001882 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001883 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001884 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001885 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001886 break;
1887 default:
David Sedlákb3077192019-06-19 10:55:37 +02001888 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001889 return LY_EVALID;
1890 }
1891 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001892 return ret;
1893}
1894
Michal Vaskoea5abea2018-09-18 13:10:54 +02001895/**
1896 * @brief Parse the pattern statement. Substatement of type statement.
1897 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001898 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001899 * @param[in,out] data Data to read from, always moved to currently handled character.
1900 * @param[in,out] patterns Restrictions to add to.
1901 *
1902 * @return LY_ERR values.
1903 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001904static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001905parse_type_pattern(struct lys_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001906{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001907 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001908 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001909 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001910 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001911 struct lysp_restr *restr;
1912
Radek Krejci2c4e7172018-10-19 15:56:26 +02001913 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001914
1915 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001916 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001917
1918 /* add special meaning first byte */
1919 if (buf) {
1920 buf = realloc(buf, word_len + 2);
1921 word = buf;
1922 } else {
1923 buf = malloc(word_len + 2);
1924 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001925 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02001926 memmove(buf + 1, word, word_len);
1927 buf[0] = 0x06; /* pattern's default regular-match flag */
1928 buf[word_len + 1] = '\0'; /* terminating NULL byte */
1929 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001930
Radek Krejci6d6556c2018-11-08 09:37:45 +01001931 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001932 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001933 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001934 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 +02001935 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001936 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001937 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 +02001938 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001939 case LY_STMT_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001940 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 +02001941 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001942 case LY_STMT_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001943 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 +02001944 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001945 case LY_STMT_MODIFIER:
Radek Krejci335332a2019-09-05 13:03:35 +02001946 PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001947 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001948 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001949 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001950 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001951 break;
1952 default:
David Sedlákb3077192019-06-19 10:55:37 +02001953 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001954 return LY_EVALID;
1955 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001956 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001957 return ret;
1958}
1959
Michal Vaskoea5abea2018-09-18 13:10:54 +02001960/**
1961 * @brief Parse the type statement.
1962 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001963 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001964 * @param[in,out] data Data to read from, always moved to currently handled character.
1965 * @param[in,out] type Type to wrote to.
1966 *
1967 * @return LY_ERR values.
1968 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001969static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02001970parse_type(struct lys_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001971{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001972 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001973 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001974 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02001975 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001976 struct lysp_type *nest_type;
1977
1978 if (type->name) {
David Sedlákb3077192019-06-19 10:55:37 +02001979 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001980 return LY_EVALID;
1981 }
1982
1983 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02001984 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001985 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001986
Radek Krejci6d6556c2018-11-08 09:37:45 +01001987 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001988 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02001989 case LY_STMT_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001990 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 +01001991 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001992 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001993 case LY_STMT_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001994 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01001995 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001996 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02001997 case LY_STMT_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001998 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01001999 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002000 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002001 case LY_STMT_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002002 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002003 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002004 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002005 case LY_STMT_LENGTH:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002006 if (type->length) {
David Sedlákb3077192019-06-19 10:55:37 +02002007 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002008 return LY_EVALID;
2009 }
2010 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002011 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002012
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002013 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002014 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002015 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002016 case LY_STMT_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002017 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 +01002018 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002019 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002020 case LY_STMT_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002021 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002022 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002023 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002024 case LY_STMT_RANGE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002025 if (type->range) {
David Sedlákb3077192019-06-19 10:55:37 +02002026 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002027 return LY_EVALID;
2028 }
2029 type->range = calloc(1, sizeof *type->range);
David Sedlák7a8b2472019-07-11 15:08:34 +02002030 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002031
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002032 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002033 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002034 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002035 case LY_STMT_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002036 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002037 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002038 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002039 case LY_STMT_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002040 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2041 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002042 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002043 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002044 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002045 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002046 break;
2047 default:
David Sedlákb3077192019-06-19 10:55:37 +02002048 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002049 return LY_EVALID;
2050 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002051 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002052 return ret;
2053}
2054
Michal Vaskoea5abea2018-09-18 13:10:54 +02002055/**
2056 * @brief Parse the leaf statement.
2057 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002058 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002059 * @param[in,out] data Data to read from, always moved to currently handled character.
2060 * @param[in,out] siblings Siblings to add to.
2061 *
2062 * @return LY_ERR values.
2063 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002064LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002065parse_leaf(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002066{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002067 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002068 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002069 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002070 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002071 struct lysp_node_leaf *leaf;
2072
David Sedlák60adc092019-08-06 15:57:02 +02002073 /* create new leaf structure */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02002074 LY_LIST_NEW_RET(ctx->ctx, siblings, leaf, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002075 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002076 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002077
Michal Vasko7fbc8162018-09-17 10:35:16 +02002078 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002079 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002080 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002081
2082 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002083 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002084 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002085 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002086 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002087 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002088 case LY_STMT_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002089 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 +02002090 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002091 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002092 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 +02002093 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002094 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002095 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 +02002096 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002097 case LY_STMT_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002098 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002099 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002100 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002101 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002102 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002103 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002104 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 +02002105 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002106 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002107 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002108 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002109 case LY_STMT_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002110 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002111 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002112 case LY_STMT_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002113 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 +02002114 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002115 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002116 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002117 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002118 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002119 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002120 break;
2121 default:
David Sedlákb3077192019-06-19 10:55:37 +02002122 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002123 return LY_EVALID;
2124 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002125 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002126 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002127checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002128 /* mandatory substatements */
2129 if (!leaf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002130 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002131 return LY_EVALID;
2132 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002133 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
David Sedlákb3077192019-06-19 10:55:37 +02002134 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002135 return LY_EVALID;
2136 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002137
2138 return ret;
2139}
2140
Michal Vaskoea5abea2018-09-18 13:10:54 +02002141/**
2142 * @brief Parse the max-elements statement.
2143 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002144 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002145 * @param[in,out] data Data to read from, always moved to currently handled character.
2146 * @param[in,out] max Value to write to.
2147 * @param[in,out] flags Flags to write to.
2148 * @param[in,out] exts Extension instances to add to.
2149 *
2150 * @return LY_ERR values.
2151 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002152LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002153parse_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 +02002154{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002155 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002156 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002157 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002158 unsigned long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02002159 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002160
2161 if (*flags & LYS_SET_MAX) {
David Sedlákb3077192019-06-19 10:55:37 +02002162 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002163 return LY_EVALID;
2164 }
2165 *flags |= LYS_SET_MAX;
2166
2167 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002168 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002169
2170 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
David Sedlákb3077192019-06-19 10:55:37 +02002171 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002172 free(buf);
2173 return LY_EVALID;
2174 }
2175
Radek Krejci7f9b6512019-09-18 13:11:09 +02002176 if (ly_strncmp("unbounded", word, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002177 errno = 0;
2178 num = strtoul(word, &ptr, 10);
2179 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002180 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002181 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002182 free(buf);
2183 return LY_EVALID;
2184 }
2185 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002186 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002187 free(buf);
2188 return LY_EVALID;
2189 }
2190
2191 *max = num;
2192 }
2193 free(buf);
2194
Radek Krejci6d6556c2018-11-08 09:37:45 +01002195 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002196 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002197 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002198 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002199 break;
2200 default:
David Sedlákb3077192019-06-19 10:55:37 +02002201 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002202 return LY_EVALID;
2203 }
2204 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002205 return ret;
2206}
2207
Michal Vaskoea5abea2018-09-18 13:10:54 +02002208/**
2209 * @brief Parse the min-elements statement.
2210 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002211 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002212 * @param[in,out] data Data to read from, always moved to currently handled character.
2213 * @param[in,out] min Value to write to.
2214 * @param[in,out] flags Flags to write to.
2215 * @param[in,out] exts Extension instances to add to.
2216 *
2217 * @return LY_ERR values.
2218 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002219LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002220parse_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 +02002221{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002222 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002223 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002224 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002225 unsigned long int num;
Radek Krejcid6b76452019-09-03 17:03:03 +02002226 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002227
2228 if (*flags & LYS_SET_MIN) {
David Sedlákb3077192019-06-19 10:55:37 +02002229 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002230 return LY_EVALID;
2231 }
2232 *flags |= LYS_SET_MIN;
2233
2234 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002235 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002236
2237 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
David Sedlákb3077192019-06-19 10:55:37 +02002238 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002239 free(buf);
2240 return LY_EVALID;
2241 }
2242
2243 errno = 0;
2244 num = strtoul(word, &ptr, 10);
2245 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002246 if ((size_t)(ptr - word) != word_len) {
David Sedlákb3077192019-06-19 10:55:37 +02002247 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002248 free(buf);
2249 return LY_EVALID;
2250 }
2251 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlákb3077192019-06-19 10:55:37 +02002252 LOGVAL_PARSER(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002253 free(buf);
2254 return LY_EVALID;
2255 }
2256 *min = num;
2257 free(buf);
2258
Radek Krejci6d6556c2018-11-08 09:37:45 +01002259 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002260 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002261 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002262 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002263 break;
2264 default:
David Sedlákb3077192019-06-19 10:55:37 +02002265 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002266 return LY_EVALID;
2267 }
2268 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002269 return ret;
2270}
2271
Michal Vaskoea5abea2018-09-18 13:10:54 +02002272/**
2273 * @brief Parse the ordered-by statement.
2274 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002275 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002276 * @param[in,out] data Data to read from, always moved to currently handled character.
2277 * @param[in,out] flags Flags to write to.
2278 * @param[in,out] exts Extension instances to add to.
2279 *
2280 * @return LY_ERR values.
2281 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002282static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002283parse_orderedby(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002284{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002285 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002286 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002287 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002288 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002289
2290 if (*flags & LYS_ORDBY_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02002291 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002292 return LY_EVALID;
2293 }
2294
2295 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002296 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002297
2298 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2299 *flags |= LYS_ORDBY_SYSTEM;
2300 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2301 *flags |= LYS_ORDBY_USER;
2302 } else {
David Sedlákb3077192019-06-19 10:55:37 +02002303 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002304 free(buf);
2305 return LY_EVALID;
2306 }
2307 free(buf);
2308
Radek Krejci6d6556c2018-11-08 09:37:45 +01002309 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002310 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002311 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002312 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002313 break;
2314 default:
David Sedlákb3077192019-06-19 10:55:37 +02002315 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002316 return LY_EVALID;
2317 }
2318 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002319 return ret;
2320}
2321
Michal Vaskoea5abea2018-09-18 13:10:54 +02002322/**
2323 * @brief Parse the leaf-list statement.
2324 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002325 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002326 * @param[in,out] data Data to read from, always moved to currently handled character.
2327 * @param[in,out] siblings Siblings to add to.
2328 *
2329 * @return LY_ERR values.
2330 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002331LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002332parse_leaflist(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002333{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002334 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002335 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002336 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002337 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002338 struct lysp_node_leaflist *llist;
2339
David Sedlák60adc092019-08-06 15:57:02 +02002340 /* create new leaf-list structure */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02002341 LY_LIST_NEW_RET(ctx->ctx, siblings, llist, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002342 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002343 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002344
Michal Vasko7fbc8162018-09-17 10:35:16 +02002345 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002346 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002347 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002348
2349 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002350 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002351 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002352 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002353 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002354 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002355 case LY_STMT_DEFAULT:
Radek Krejci335332a2019-09-05 13:03:35 +02002356 PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002357 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 +02002358 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002359 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002360 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 +02002361 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002362 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002363 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 +02002364 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002365 case LY_STMT_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002366 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002367 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002368 case LY_STMT_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002369 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002370 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002371 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002372 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002373 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002374 case LY_STMT_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002375 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002376 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002377 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002378 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 +02002379 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002380 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002381 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002382 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002383 case LY_STMT_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002384 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002385 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002386 case LY_STMT_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002387 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 +02002388 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002389 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002390 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002391 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002392 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002393 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002394 break;
2395 default:
David Sedlákb3077192019-06-19 10:55:37 +02002396 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002397 return LY_EVALID;
2398 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002399 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002400 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002401checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002402 /* mandatory substatements */
2403 if (!llist->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002404 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002405 return LY_EVALID;
2406 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01002407 if ((llist->min) && (llist->dflts)) {
David Sedlákb3077192019-06-19 10:55:37 +02002408 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
Radek Krejci0e5d8382018-11-28 16:37:53 +01002409 return LY_EVALID;
2410 }
Radek Krejcidf6cad12018-11-28 17:10:55 +01002411 if (llist->max && llist->min > llist->max) {
David Sedlákb3077192019-06-19 10:55:37 +02002412 LOGVAL_PARSER(ctx, LYVE_SEMANTICS,
Radek Krejcidf6cad12018-11-28 17:10:55 +01002413 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
2414 llist->min, llist->max);
2415 return LY_EVALID;
2416 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002417
2418 return ret;
2419}
2420
Michal Vaskoea5abea2018-09-18 13:10:54 +02002421/**
2422 * @brief Parse the refine statement.
2423 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002424 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002425 * @param[in,out] data Data to read from, always moved to currently handled character.
2426 * @param[in,out] refines Refines to add to.
2427 *
2428 * @return LY_ERR values.
2429 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002430static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002431parse_refine(struct lys_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002432{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002433 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002434 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002435 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002436 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002437 struct lysp_refine *rf;
2438
Radek Krejci2c4e7172018-10-19 15:56:26 +02002439 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002440
2441 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002442 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
David Sedlákb9b892c2019-07-12 14:44:02 +02002443 YANG_CHECK_NONEMPTY(ctx, word_len, "refine");
Radek Krejci44ceedc2018-10-02 15:54:31 +02002444 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002445
Radek Krejci6d6556c2018-11-08 09:37:45 +01002446 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002447 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002448 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002449 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002450 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002451 case LY_STMT_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002452 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 +02002453 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002454 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002455 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 +02002456 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002457 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02002458 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002459 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 +02002460 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002461 case LY_STMT_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002462 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002463 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002464 case LY_STMT_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002465 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002466 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002467 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002468 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002469 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002470 case LY_STMT_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002471 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002472 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002473 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002474 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 +02002475 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002476 case LY_STMT_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002477 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 +02002478 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002479 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002480 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002481 break;
2482 default:
David Sedlákb3077192019-06-19 10:55:37 +02002483 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002484 return LY_EVALID;
2485 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002486 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002487 return ret;
2488}
2489
Michal Vaskoea5abea2018-09-18 13:10:54 +02002490/**
2491 * @brief Parse the typedef statement.
2492 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002493 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002494 * @param[in,out] data Data to read from, always moved to currently handled character.
2495 * @param[in,out] typedefs Typedefs to add to.
2496 *
2497 * @return LY_ERR values.
2498 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002499static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002500parse_typedef(struct lys_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002501{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002502 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002503 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002504 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002505 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002506 struct lysp_tpdf *tpdf;
2507
Radek Krejci2c4e7172018-10-19 15:56:26 +02002508 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002509
2510 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002511 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002512 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002513
2514 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002515 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002516 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002517 case LY_STMT_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002518 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 +02002519 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002520 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002521 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 +02002522 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002523 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002524 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 +02002525 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002526 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002527 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002528 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002529 case LY_STMT_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002530 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002531 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002532 case LY_STMT_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002533 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 +02002534 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002535 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002536 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002537 break;
2538 default:
David Sedlákb3077192019-06-19 10:55:37 +02002539 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002540 return LY_EVALID;
2541 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002542 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002543 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002544checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002545 /* mandatory substatements */
2546 if (!tpdf->type.name) {
David Sedlákb3077192019-06-19 10:55:37 +02002547 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002548 return LY_EVALID;
2549 }
2550
Radek Krejcibbe09a92018-11-08 09:36:54 +01002551 /* store data for collision check */
Radek Krejci7fc68292019-06-12 13:51:09 +02002552 if (parent && !(parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
David Sedláke8b74df2019-08-14 14:18:22 +02002553 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, parent, 0) == -1, LY_EMEM);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002554 }
2555
Michal Vasko7fbc8162018-09-17 10:35:16 +02002556 return ret;
2557}
2558
Michal Vaskoea5abea2018-09-18 13:10:54 +02002559/**
2560 * @brief Parse the input or output statement.
2561 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002562 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002563 * @param[in,out] data Data to read from, always moved to currently handled character.
2564 * @param[in] kw Type of this particular keyword
2565 * @param[in,out] inout_p Input/output pointer to write to.
2566 *
2567 * @return LY_ERR values.
2568 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002569static LY_ERR
Radek Krejcid6b76452019-09-03 17:03:03 +02002570parse_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 +02002571{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002572 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002573 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002574 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002575 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002576
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002577 if (inout_p->nodetype) {
David Sedlákb3077192019-06-19 10:55:37 +02002578 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002579 return LY_EVALID;
2580 }
2581
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002582 /* initiate structure */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002583 inout_p->nodetype = &((struct lysp_action*)parent)->input == inout_p ? LYS_INPUT : LYS_OUTPUT;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002584 inout_p->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002585
2586 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02002587 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002588 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002589 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002590 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
Radek Krejci10113652018-11-14 16:56:50 +01002591 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002592 case LY_STMT_ANYXML:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002593 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002594 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002595 case LY_STMT_CHOICE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002596 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002597 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002598 case LY_STMT_CONTAINER:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002599 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002600 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002601 case LY_STMT_LEAF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002602 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002603 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002604 case LY_STMT_LEAF_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002605 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002606 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002607 case LY_STMT_LIST:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002608 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002609 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002610 case LY_STMT_USES:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002611 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002612 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002613 case LY_STMT_TYPEDEF:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002614 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002615 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002616 case LY_STMT_MUST:
Radek Krejci335332a2019-09-05 13:03:35 +02002617 PARSER_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002618 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002619 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002620 case LY_STMT_GROUPING:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002621 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002622 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002623 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6eeb58f2019-02-22 16:29:37 +01002624 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002625 break;
2626 default:
David Sedlákb3077192019-06-19 10:55:37 +02002627 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002628 return LY_EVALID;
2629 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002630 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002631 LY_CHECK_RET(ret);
2632checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002633 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02002634 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, inout_p->groupings, NULL, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02002635
Michal Vasko7fbc8162018-09-17 10:35:16 +02002636 return ret;
2637}
2638
Michal Vaskoea5abea2018-09-18 13:10:54 +02002639/**
2640 * @brief Parse the action statement.
2641 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002642 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002643 * @param[in,out] data Data to read from, always moved to currently handled character.
2644 * @param[in,out] actions Actions to add to.
2645 *
2646 * @return LY_ERR values.
2647 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002648LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002649parse_action(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002650{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002651 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002652 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002653 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002654 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002655 struct lysp_action *act;
2656
Radek Krejci2c4e7172018-10-19 15:56:26 +02002657 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002658
2659 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002660 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002661 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002662 act->nodetype = LYS_ACTION;
2663 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002664
Radek Krejci7fc68292019-06-12 13:51:09 +02002665 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002666 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002667 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002668 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 +02002669 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002670 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002671 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 +02002672 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002673 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002674 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 +02002675 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002676 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002677 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002678 break;
2679
Radek Krejcid6b76452019-09-03 17:03:03 +02002680 case LY_STMT_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002681 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002682 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002683 case LY_STMT_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002684 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002685 break;
2686
Radek Krejcid6b76452019-09-03 17:03:03 +02002687 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002688 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002689 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002690 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002691 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002692 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002693 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002694 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002695 break;
2696 default:
David Sedlákb3077192019-06-19 10:55:37 +02002697 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002698 return LY_EVALID;
2699 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002700 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002701 LY_CHECK_RET(ret);
2702checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002703 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02002704 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, act->groupings, NULL, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02002705
Michal Vasko7fbc8162018-09-17 10:35:16 +02002706 return ret;
2707}
2708
Michal Vaskoea5abea2018-09-18 13:10:54 +02002709/**
2710 * @brief Parse the notification statement.
2711 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002712 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002713 * @param[in,out] data Data to read from, always moved to currently handled character.
2714 * @param[in,out] notifs Notifications to add to.
2715 *
2716 * @return LY_ERR values.
2717 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002718LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002719parse_notif(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002720{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002721 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002722 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002723 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002724 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002725 struct lysp_notif *notif;
2726
Radek Krejci2c4e7172018-10-19 15:56:26 +02002727 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002728
2729 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002730 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002731 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002732 notif->nodetype = LYS_NOTIF;
2733 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002734
Radek Krejci7fc68292019-06-12 13:51:09 +02002735 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002736 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002737 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002738 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 +02002739 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002740 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002741 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 +02002742 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002743 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002744 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 +02002745 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002746 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002747 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002748 break;
2749
Radek Krejcid6b76452019-09-03 17:03:03 +02002750 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002751 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
Radek Krejci10113652018-11-14 16:56:50 +01002752 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002753 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002754 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002755 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002756 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002757 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002758 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002759 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002760 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002761 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002762 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002763 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002764 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002765 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002766 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002767 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002768 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002769 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002770 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002771 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002772 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002773 break;
2774
Radek Krejcid6b76452019-09-03 17:03:03 +02002775 case LY_STMT_MUST:
Radek Krejci335332a2019-09-05 13:03:35 +02002776 PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002777 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002778 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002779 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002780 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002781 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002782 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002783 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002784 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002785 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002786 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002787 break;
2788 default:
David Sedlákb3077192019-06-19 10:55:37 +02002789 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790 return LY_EVALID;
2791 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002792 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002793 LY_CHECK_RET(ret);
2794checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002795 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02002796 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, notif->groupings, NULL, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02002797
Michal Vasko7fbc8162018-09-17 10:35:16 +02002798 return ret;
2799}
2800
Michal Vaskoea5abea2018-09-18 13:10:54 +02002801/**
2802 * @brief Parse the grouping statement.
2803 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002804 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002805 * @param[in,out] data Data to read from, always moved to currently handled character.
2806 * @param[in,out] groupings Groupings to add to.
2807 *
2808 * @return LY_ERR values.
2809 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002810LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002811parse_grouping(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002812{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002813 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002814 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002815 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002816 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002817 struct lysp_grp *grp;
2818
Radek Krejci2c4e7172018-10-19 15:56:26 +02002819 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002820
2821 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002822 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002823 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002824 grp->nodetype = LYS_GROUPING;
2825 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002826
Radek Krejci7fc68292019-06-12 13:51:09 +02002827 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002828 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002829 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002830 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 +02002831 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002832 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002833 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 +02002834 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002835 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002836 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002837 break;
2838
Radek Krejcid6b76452019-09-03 17:03:03 +02002839 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002840 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
Radek Krejci10113652018-11-14 16:56:50 +01002841 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002842 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002843 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002844 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002845 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002846 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002847 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002848 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002849 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002850 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002851 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002852 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002853 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002854 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002855 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002856 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002857 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002858 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002859 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002860 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002861 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002862 break;
2863
Radek Krejcid6b76452019-09-03 17:03:03 +02002864 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002865 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002866 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002867 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02002868 PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002869 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002870 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002871 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002872 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002873 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002874 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02002875 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002876 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002877 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002878 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002879 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002880 break;
2881 default:
David Sedlákb3077192019-06-19 10:55:37 +02002882 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002883 return LY_EVALID;
2884 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002885 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002886 LY_CHECK_RET(ret);
2887checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01002888 /* finalize parent pointers to the reallocated items */
David Sedlák0d6de5a2019-07-22 13:25:44 +02002889 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, grp->groupings, NULL, grp->actions, grp->notifs));
Radek Krejci7fc68292019-06-12 13:51:09 +02002890
Michal Vasko7fbc8162018-09-17 10:35:16 +02002891 return ret;
2892}
2893
Michal Vaskoea5abea2018-09-18 13:10:54 +02002894/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02002895 * @brief Parse the augment statement.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002896 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002897 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002898 * @param[in,out] data Data to read from, always moved to currently handled character.
2899 * @param[in,out] augments Augments to add to.
2900 *
2901 * @return LY_ERR values.
2902 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002903LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02002904parse_augment(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002905{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002906 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002907 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002908 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02002909 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002910 struct lysp_augment *aug;
2911
Radek Krejci2c4e7172018-10-19 15:56:26 +02002912 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002913
2914 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02002915 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
David Sedlákb9b892c2019-07-12 14:44:02 +02002916 YANG_CHECK_NONEMPTY(ctx, word_len, "augment");
Radek Krejci44ceedc2018-10-02 15:54:31 +02002917 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002918 aug->nodetype = LYS_AUGMENT;
2919 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002920
Radek Krejci7fc68292019-06-12 13:51:09 +02002921 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002922 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002923 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002924 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 +02002925 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002926 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002927 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 +02002928 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002929 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002930 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 +02002931 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002932 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002933 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002934 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002935 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002936 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002937 break;
2938
Radek Krejcid6b76452019-09-03 17:03:03 +02002939 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02002940 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
Radek Krejci10113652018-11-14 16:56:50 +01002941 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02002942 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002943 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002944 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002945 case LY_STMT_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002946 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002947 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002948 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002949 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002950 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002951 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002952 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002953 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002954 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002955 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002956 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002957 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002958 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002959 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002960 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002961 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002962 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002963 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002964 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002965 break;
2966
Radek Krejcid6b76452019-09-03 17:03:03 +02002967 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02002968 PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002969 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002970 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002971 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02002972 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002973 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002974 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02002975 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002976 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002977 break;
2978 default:
David Sedlákb3077192019-06-19 10:55:37 +02002979 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002980 return LY_EVALID;
2981 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002982 }
Radek Krejci7fc68292019-06-12 13:51:09 +02002983 LY_CHECK_RET(ret);
2984checks:
2985 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02002986 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, NULL, NULL, aug->actions, aug->notifs));
Radek Krejci7fc68292019-06-12 13:51:09 +02002987
Michal Vasko7fbc8162018-09-17 10:35:16 +02002988 return ret;
2989}
2990
Michal Vaskoea5abea2018-09-18 13:10:54 +02002991/**
2992 * @brief Parse the uses statement.
2993 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002994 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002995 * @param[in,out] data Data to read from, always moved to currently handled character.
2996 * @param[in,out] siblings Siblings to add to.
2997 *
2998 * @return LY_ERR values.
2999 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003000LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003001parse_uses(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003002{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003003 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003004 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003005 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003006 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003007 struct lysp_node_uses *uses;
3008
David Sedlák60adc092019-08-06 15:57:02 +02003009 /* create uses structure */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02003010 LY_LIST_NEW_RET(ctx->ctx, siblings, uses, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003011 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003012 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003013
Michal Vasko7fbc8162018-09-17 10:35:16 +02003014 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003015 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003016 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003017
3018 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003019 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003020 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003021 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003022 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 +02003023 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003024 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003025 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 +02003026 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003027 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003028 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 +02003029 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003030 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003031 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003033 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003034 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003035 break;
3036
Radek Krejcid6b76452019-09-03 17:03:03 +02003037 case LY_STMT_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003038 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003039 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003040 case LY_STMT_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003041 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003042 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003043 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003044 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003045 break;
3046 default:
David Sedlákb3077192019-06-19 10:55:37 +02003047 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003048 return LY_EVALID;
3049 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003050 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003051checks:
3052 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02003053 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, NULL, uses->augments, NULL, NULL));
Radek Krejci7fc68292019-06-12 13:51:09 +02003054
Michal Vasko7fbc8162018-09-17 10:35:16 +02003055 return ret;
3056}
3057
Michal Vaskoea5abea2018-09-18 13:10:54 +02003058/**
3059 * @brief Parse the case statement.
3060 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003061 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003062 * @param[in,out] data Data to read from, always moved to currently handled character.
3063 * @param[in,out] siblings Siblings to add to.
3064 *
3065 * @return LY_ERR values.
3066 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003067LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003068parse_case(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003069{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003070 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003071 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003072 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003073 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003074 struct lysp_node_case *cas;
3075
David Sedlák60adc092019-08-06 15:57:02 +02003076 /* create new case structure */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02003077 LY_LIST_NEW_RET(ctx->ctx, siblings, cas, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003078 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003079 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003080
Michal Vasko7fbc8162018-09-17 10:35:16 +02003081 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003082 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003083 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003084
3085 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003086 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003087 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003088 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003089 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 +02003090 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003091 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003092 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 +02003093 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003094 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003095 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 +02003096 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003097 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003098 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003099 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003100 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003101 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003102 break;
3103
Radek Krejcid6b76452019-09-03 17:03:03 +02003104 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003105 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
Radek Krejci10113652018-11-14 16:56:50 +01003106 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003107 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003108 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003109 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003110 case LY_STMT_CHOICE:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003111 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003112 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003113 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003114 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003115 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003116 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003117 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003118 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003119 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003120 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003121 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003122 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003123 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003124 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003125 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003126 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003127 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003128 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003129 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003130 break;
3131 default:
David Sedlákb3077192019-06-19 10:55:37 +02003132 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003133 return LY_EVALID;
3134 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003136 return ret;
3137}
3138
Michal Vaskoea5abea2018-09-18 13:10:54 +02003139/**
3140 * @brief Parse the choice statement.
3141 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003142 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003143 * @param[in,out] data Data to read from, always moved to currently handled character.
3144 * @param[in,out] siblings Siblings to add to.
3145 *
3146 * @return LY_ERR values.
3147 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003148LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003149parse_choice(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003150{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003151 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003152 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003153 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003154 enum ly_stmt kw;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003155 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003156
David Sedlák60adc092019-08-06 15:57:02 +02003157 /* create new choice structure */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02003158 LY_LIST_NEW_RET(ctx->ctx, siblings, choice, next, LY_EMEM);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003159 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003160 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003161
Michal Vasko7fbc8162018-09-17 10:35:16 +02003162 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003163 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003164 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003165
3166 /* parse substatements */
Radek Krejcia9026eb2018-12-12 16:04:47 +01003167 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003168 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003169 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003170 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003171 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003172 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003173 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 +02003174 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003175 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003176 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 +02003177 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003178 case LY_STMT_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003179 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003180 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003181 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003182 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 +02003183 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003184 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003185 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003186 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003187 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003188 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003189 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003190 case LY_STMT_DEFAULT:
Radek Krejcia9026eb2018-12-12 16:04:47 +01003191 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 +02003192 break;
3193
Radek Krejcid6b76452019-09-03 17:03:03 +02003194 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003195 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
Radek Krejci10113652018-11-14 16:56:50 +01003196 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003197 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003198 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003199 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003200 case LY_STMT_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003201 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003202 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003203 case LY_STMT_CHOICE:
Radek Krejci335332a2019-09-05 13:03:35 +02003204 PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003205 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003206 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003207 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003208 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003209 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003210 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003211 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003212 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003213 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003214 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003215 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003216 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003217 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003218 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003219 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003220 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003221 break;
3222 default:
David Sedlákb3077192019-06-19 10:55:37 +02003223 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224 return LY_EVALID;
3225 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003226 }
Radek Krejcia9026eb2018-12-12 16:04:47 +01003227 LY_CHECK_RET(ret);
3228checks:
3229 if ((choice->flags & LYS_MAND_TRUE) && choice->dflt) {
David Sedlákb3077192019-06-19 10:55:37 +02003230 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "choice");
Radek Krejcia9026eb2018-12-12 16:04:47 +01003231 return LY_EVALID;
3232 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003233 return ret;
3234}
3235
Michal Vaskoea5abea2018-09-18 13:10:54 +02003236/**
3237 * @brief Parse the container statement.
3238 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003239 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003240 * @param[in,out] data Data to read from, always moved to currently handled character.
3241 * @param[in,out] siblings Siblings to add to.
3242 *
3243 * @return LY_ERR values.
3244 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003245LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003246parse_container(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003247{
3248 LY_ERR ret = 0;
3249 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003250 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003251 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003252 struct lysp_node_container *cont;
3253
David Sedlák60adc092019-08-06 15:57:02 +02003254 /* create new container structure */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02003255 LY_LIST_NEW_RET(ctx->ctx, siblings, cont, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003256 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003257 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003258
Michal Vasko7fbc8162018-09-17 10:35:16 +02003259 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003260 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003261 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003262
3263 /* parse substatements */
Radek Krejci7fc68292019-06-12 13:51:09 +02003264 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003265 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003266 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003267 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003268 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003269 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003270 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 +02003271 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003272 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003273 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 +02003274 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003275 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003276 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 +02003277 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003278 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003279 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003280 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003281 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003282 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003283 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003284 case LY_STMT_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003285 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 +02003286 break;
3287
Radek Krejcid6b76452019-09-03 17:03:03 +02003288 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003289 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
Radek Krejci10113652018-11-14 16:56:50 +01003290 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003291 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003292 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003293 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003294 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003295 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003296 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003297 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003298 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003299 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003300 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003301 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003302 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003303 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003304 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003305 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003306 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003307 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003308 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003309 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003310 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003311 break;
3312
Radek Krejcid6b76452019-09-03 17:03:03 +02003313 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003314 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003315 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003316 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003317 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003318 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003319 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02003320 PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003321 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003322 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003323 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003324 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003325 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003326 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02003327 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003328 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003329 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003330 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003331 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003332 break;
3333 default:
David Sedlákb3077192019-06-19 10:55:37 +02003334 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003335 return LY_EVALID;
3336 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003337 }
Radek Krejci7fc68292019-06-12 13:51:09 +02003338checks:
Radek Krejcie86bf772018-12-14 11:39:53 +01003339 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02003340 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, cont->groupings, NULL, cont->actions, cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003341 return ret;
3342}
3343
Michal Vaskoea5abea2018-09-18 13:10:54 +02003344/**
3345 * @brief Parse the list statement.
3346 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003347 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003348 * @param[in,out] data Data to read from, always moved to currently handled character.
3349 * @param[in,out] siblings Siblings to add to.
3350 *
3351 * @return LY_ERR values.
3352 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003353LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003354parse_list(struct lys_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003355{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003356 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003357 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003358 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003359 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003360 struct lysp_node_list *list;
3361
David Sedlák60adc092019-08-06 15:57:02 +02003362 /* create new list structure */
David Sedlákb9eeb9c2019-09-13 11:17:19 +02003363 LY_LIST_NEW_RET(ctx->ctx, siblings, list, next, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003364 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003365 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003366
Michal Vasko7fbc8162018-09-17 10:35:16 +02003367 /* get name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003368 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003369 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003370
3371 /* parse substatements */
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003372 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003373 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003374 case LY_STMT_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003375 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003376 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003377 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003378 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 +02003379 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003380 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003381 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 +02003382 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003383 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003384 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 +02003385 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003386 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003387 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003388 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003389 case LY_STMT_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003390 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003391 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003392 case LY_STMT_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003393 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 +02003394 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003395 case LY_STMT_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003396 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003397 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003398 case LY_STMT_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003399 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003400 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003401 case LY_STMT_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003402 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003403 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003404 case LY_STMT_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003405 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 +02003406 break;
3407
Radek Krejcid6b76452019-09-03 17:03:03 +02003408 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02003409 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
Radek Krejci10113652018-11-14 16:56:50 +01003410 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02003411 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003412 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003413 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003414 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003415 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003416 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003417 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003418 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003419 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003420 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003421 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003422 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003423 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003424 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003425 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003426 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003427 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003428 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003429 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003430 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003431 break;
3432
Radek Krejcid6b76452019-09-03 17:03:03 +02003433 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003434 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003435 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003436 case LY_STMT_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003437 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003438 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003439 case LY_STMT_ACTION:
Radek Krejci335332a2019-09-05 13:03:35 +02003440 PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003441 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003442 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003443 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003444 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003445 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003446 case LY_STMT_NOTIFICATION:
Radek Krejci335332a2019-09-05 13:03:35 +02003447 PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003448 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003449 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003450 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003451 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003452 break;
3453 default:
David Sedlákb3077192019-06-19 10:55:37 +02003454 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003455 return LY_EVALID;
3456 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003457 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003458 LY_CHECK_RET(ret);
3459checks:
Radek Krejci7fc68292019-06-12 13:51:09 +02003460 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02003461 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, list->groupings, NULL, list->actions, list->notifs));
Radek Krejci7fc68292019-06-12 13:51:09 +02003462
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003463 if (list->max && list->min > list->max) {
David Sedlákb3077192019-06-19 10:55:37 +02003464 LOGVAL_PARSER(ctx, LYVE_SEMANTICS,
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003465 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
3466 list->min, list->max);
3467 return LY_EVALID;
3468 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003469
3470 return ret;
3471}
3472
Michal Vaskoea5abea2018-09-18 13:10:54 +02003473/**
3474 * @brief Parse the yin-element statement.
3475 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003476 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003477 * @param[in,out] data Data to read from, always moved to currently handled character.
3478 * @param[in,out] flags Flags to write to.
3479 * @param[in,out] exts Extension instances to add to.
3480 *
3481 * @return LY_ERR values.
3482 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003483static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003484parse_yinelement(struct lys_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003485{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003486 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003487 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003488 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003489 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003490
3491 if (*flags & LYS_YINELEM_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +02003492 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003493 return LY_EVALID;
3494 }
3495
3496 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003497 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003498
3499 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3500 *flags |= LYS_YINELEM_TRUE;
3501 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3502 *flags |= LYS_YINELEM_FALSE;
3503 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003504 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003505 free(buf);
3506 return LY_EVALID;
3507 }
3508 free(buf);
3509
Radek Krejci6d6556c2018-11-08 09:37:45 +01003510 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003511 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003512 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003513 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3514 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003515 default:
David Sedlákb3077192019-06-19 10:55:37 +02003516 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003517 return LY_EVALID;
3518 }
3519 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003520 return ret;
3521}
3522
Michal Vaskoea5abea2018-09-18 13:10:54 +02003523/**
David Sedlák2444f8f2019-07-09 11:02:47 +02003524 * @brief Parse the argument statement.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003525 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003526 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003527 * @param[in,out] data Data to read from, always moved to currently handled character.
3528 * @param[in,out] argument Value to write to.
3529 * @param[in,out] flags Flags to write to.
3530 * @param[in,out] exts Extension instances to add to.
3531 *
3532 * @return LY_ERR values.
3533 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003534static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003535parse_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 +02003536{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003537 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003538 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003539 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003540 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003541
3542 if (*argument) {
David Sedlákb3077192019-06-19 10:55:37 +02003543 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003544 return LY_EVALID;
3545 }
3546
3547 /* get value */
David Sedlák2444f8f2019-07-09 11:02:47 +02003548 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003549 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003550
Radek Krejci6d6556c2018-11-08 09:37:45 +01003551 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003552 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003553 case LY_STMT_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003554 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003555 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003556 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003557 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003558 break;
3559 default:
David Sedlákb3077192019-06-19 10:55:37 +02003560 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003561 return LY_EVALID;
3562 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003563 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003564 return ret;
3565}
3566
Michal Vaskoea5abea2018-09-18 13:10:54 +02003567/**
3568 * @brief Parse the extension statement.
3569 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003570 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003571 * @param[in,out] data Data to read from, always moved to currently handled character.
3572 * @param[in,out] extensions Extensions to add to.
3573 *
3574 * @return LY_ERR values.
3575 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003576static LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003577parse_extension(struct lys_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003578{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003579 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003580 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003581 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003582 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003583 struct lysp_ext *ex;
3584
Radek Krejci2c4e7172018-10-19 15:56:26 +02003585 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003586
3587 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003588 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003589 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590
Radek Krejci6d6556c2018-11-08 09:37:45 +01003591 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003592 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003593 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003594 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 +02003595 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003596 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003597 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 +02003598 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003599 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003600 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003601 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003602 case LY_STMT_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003603 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003604 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003605 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003606 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003607 break;
3608 default:
David Sedlákb3077192019-06-19 10:55:37 +02003609 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610 return LY_EVALID;
3611 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003612 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003613 return ret;
3614}
3615
Michal Vaskoea5abea2018-09-18 13:10:54 +02003616/**
3617 * @brief Parse the deviate statement.
3618 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003619 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003620 * @param[in,out] data Data to read from, always moved to currently handled character.
3621 * @param[in,out] deviates Deviates to add to.
3622 *
3623 * @return LY_ERR values.
3624 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003625LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003626parse_deviate(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003627{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003628 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003629 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003630 size_t word_len, dev_mod;
Radek Krejcid6b76452019-09-03 17:03:03 +02003631 enum ly_stmt kw;
David Sedlák60adc092019-08-06 15:57:02 +02003632 struct lysp_deviate *d;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003633 struct lysp_deviate_add *d_add = NULL;
3634 struct lysp_deviate_rpl *d_rpl = NULL;
3635 struct lysp_deviate_del *d_del = NULL;
Radek Krejci4ad42aa2019-07-23 16:55:58 +02003636 const char **d_units = NULL, ***d_uniques = NULL, ***d_dflts = NULL;
3637 struct lysp_restr **d_musts = NULL;
3638 uint16_t *d_flags = 0;
3639 uint32_t *d_min = 0, *d_max = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003640
3641 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003642 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643
3644 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3645 dev_mod = LYS_DEV_NOT_SUPPORTED;
3646 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3647 dev_mod = LYS_DEV_ADD;
3648 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3649 dev_mod = LYS_DEV_REPLACE;
3650 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3651 dev_mod = LYS_DEV_DELETE;
3652 } else {
David Sedlákb3077192019-06-19 10:55:37 +02003653 LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003654 free(buf);
3655 return LY_EVALID;
3656 }
3657 free(buf);
3658
3659 /* create structure */
3660 switch (dev_mod) {
3661 case LYS_DEV_NOT_SUPPORTED:
3662 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003663 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003664 break;
3665 case LYS_DEV_ADD:
3666 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003667 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003668 d = (struct lysp_deviate *)d_add;
3669 d_units = &d_add->units;
3670 d_uniques = &d_add->uniques;
3671 d_dflts = &d_add->dflts;
3672 d_musts = &d_add->musts;
3673 d_flags = &d_add->flags;
3674 d_min = &d_add->min;
3675 d_max = &d_add->max;
3676 break;
3677 case LYS_DEV_REPLACE:
3678 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003679 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003680 d = (struct lysp_deviate *)d_rpl;
3681 d_units = &d_rpl->units;
3682 d_flags = &d_rpl->flags;
3683 d_min = &d_rpl->min;
3684 d_max = &d_rpl->max;
3685 break;
3686 case LYS_DEV_DELETE:
3687 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003688 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003689 d = (struct lysp_deviate *)d_del;
3690 d_units = &d_del->units;
3691 d_uniques = &d_del->uniques;
3692 d_dflts = &d_del->dflts;
3693 d_musts = &d_del->musts;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003694 break;
3695 default:
3696 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003697 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003698 }
3699 d->mod = dev_mod;
3700
3701 /* insert into siblings */
David Sedlák60adc092019-08-06 15:57:02 +02003702 LY_LIST_INSERT(deviates, d, next);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003703
Radek Krejci6d6556c2018-11-08 09:37:45 +01003704 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003705 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003706 case LY_STMT_CONFIG:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003707 switch (dev_mod) {
3708 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003709 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003710 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003711 return LY_EVALID;
3712 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003713 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003714 break;
3715 }
3716 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003717 case LY_STMT_DEFAULT:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003718 switch (dev_mod) {
3719 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02003720 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003721 return LY_EVALID;
3722 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003723 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 +02003724 break;
3725 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003726 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 +02003727 break;
3728 }
3729 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003730 case LY_STMT_MANDATORY:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003731 switch (dev_mod) {
3732 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003733 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003734 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003735 return LY_EVALID;
3736 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003737 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003738 break;
3739 }
3740 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003741 case LY_STMT_MAX_ELEMENTS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003742 switch (dev_mod) {
3743 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003744 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003745 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003746 return LY_EVALID;
3747 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003748 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003749 break;
3750 }
3751 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003752 case LY_STMT_MIN_ELEMENTS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003753 switch (dev_mod) {
3754 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003755 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003756 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003757 return LY_EVALID;
3758 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003759 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003760 break;
3761 }
3762 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003763 case LY_STMT_MUST:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003764 switch (dev_mod) {
3765 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003766 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02003767 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003768 return LY_EVALID;
3769 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003770 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003771 break;
3772 }
3773 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003774 case LY_STMT_TYPE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003775 switch (dev_mod) {
3776 case LYS_DEV_NOT_SUPPORTED:
3777 case LYS_DEV_ADD:
3778 case LYS_DEV_DELETE:
David Sedlákb3077192019-06-19 10:55:37 +02003779 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003780 return LY_EVALID;
3781 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003782 if (d_rpl->type) {
David Sedlákb3077192019-06-19 10:55:37 +02003783 LOGVAL_PARSER(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003784 return LY_EVALID;
3785 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003786 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003787 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003788 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003789 break;
3790 }
3791 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003792 case LY_STMT_UNIQUE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003793 switch (dev_mod) {
3794 case LYS_DEV_NOT_SUPPORTED:
3795 case LYS_DEV_REPLACE:
David Sedlákb3077192019-06-19 10:55:37 +02003796 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003797 return LY_EVALID;
3798 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003799 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 +02003800 break;
3801 }
3802 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003803 case LY_STMT_UNITS:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003804 switch (dev_mod) {
3805 case LYS_DEV_NOT_SUPPORTED:
David Sedlákb3077192019-06-19 10:55:37 +02003806 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003807 return LY_EVALID;
3808 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003809 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 +02003810 break;
3811 }
3812 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003813 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003814 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003815 break;
3816 default:
David Sedlákb3077192019-06-19 10:55:37 +02003817 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003818 return LY_EVALID;
3819 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003820 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003821 return ret;
3822}
3823
Michal Vaskoea5abea2018-09-18 13:10:54 +02003824/**
3825 * @brief Parse the deviation statement.
3826 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003827 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003828 * @param[in,out] data Data to read from, always moved to currently handled character.
3829 * @param[in,out] deviations Deviations to add to.
3830 *
3831 * @return LY_ERR values.
3832 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003833LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003834parse_deviation(struct lys_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003835{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003836 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003837 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003838 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003839 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003840 struct lysp_deviation *dev;
3841
Radek Krejci2c4e7172018-10-19 15:56:26 +02003842 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003843
3844 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003845 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
David Sedlákb9b892c2019-07-12 14:44:02 +02003846 YANG_CHECK_NONEMPTY(ctx, word_len, "deviation");
Radek Krejci44ceedc2018-10-02 15:54:31 +02003847 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003848
Radek Krejci6d6556c2018-11-08 09:37:45 +01003849 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003850 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003851 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003852 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 +02003853 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003854 case LY_STMT_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003855 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003856 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003857 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003858 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 +02003859 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003860 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003861 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003862 break;
3863 default:
David Sedlákb3077192019-06-19 10:55:37 +02003864 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003865 return LY_EVALID;
3866 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003867 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003868 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01003869checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02003870 /* mandatory substatements */
3871 if (!dev->deviates) {
David Sedlákb3077192019-06-19 10:55:37 +02003872 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003873 return LY_EVALID;
3874 }
3875
3876 return ret;
3877}
3878
Michal Vaskoea5abea2018-09-18 13:10:54 +02003879/**
3880 * @brief Parse the feature statement.
3881 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003882 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003883 * @param[in,out] data Data to read from, always moved to currently handled character.
3884 * @param[in,out] features Features to add to.
3885 *
3886 * @return LY_ERR values.
3887 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003888LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003889parse_feature(struct lys_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003890{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003891 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003892 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003893 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003894 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003895 struct lysp_feature *feat;
3896
Radek Krejci2c4e7172018-10-19 15:56:26 +02003897 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003898
3899 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003900 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003901 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01003902
Radek Krejci6d6556c2018-11-08 09:37:45 +01003903 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003904 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003905 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003906 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 +02003907 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003908 case LY_STMT_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003909 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 +02003910 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003911 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003912 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 +02003913 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003914 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003915 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003916 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003917 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003918 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003919 break;
3920 default:
David Sedlákb3077192019-06-19 10:55:37 +02003921 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003922 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003923 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003924 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003925 return ret;
3926}
3927
Michal Vaskoea5abea2018-09-18 13:10:54 +02003928/**
3929 * @brief Parse the identity statement.
3930 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003931 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003932 * @param[in,out] data Data to read from, always moved to currently handled character.
3933 * @param[in,out] identities Identities to add to.
3934 *
3935 * @return LY_ERR values.
3936 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003937LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003938parse_identity(struct lys_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003939{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003940 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003941 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003942 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02003943 enum ly_stmt kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003944 struct lysp_ident *ident;
3945
Radek Krejci2c4e7172018-10-19 15:56:26 +02003946 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003947
3948 /* get value */
Radek Krejcid3ca0632019-04-16 16:54:54 +02003949 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003950 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01003951
Radek Krejci6d6556c2018-11-08 09:37:45 +01003952 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003953 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02003954 case LY_STMT_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003955 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 +02003956 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003957 case LY_STMT_IF_FEATURE:
Radek Krejci335332a2019-09-05 13:03:35 +02003958 PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003959 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 +02003960 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003961 case LY_STMT_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003962 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 +02003963 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003964 case LY_STMT_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003965 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003966 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003967 case LY_STMT_BASE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01003968 if (ident->bases && ctx->mod_version < 2) {
David Sedlákb3077192019-06-19 10:55:37 +02003969 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 +01003970 return LY_EVALID;
3971 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003972 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 +02003973 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02003974 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003975 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003976 break;
3977 default:
David Sedlákb3077192019-06-19 10:55:37 +02003978 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003979 return LY_EVALID;
3980 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003981 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003982 return ret;
3983}
3984
Michal Vaskoea5abea2018-09-18 13:10:54 +02003985/**
Radek Krejci0bcdaed2019-01-10 10:21:34 +01003986 * @brief Parse module substatements.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003987 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003988 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003989 * @param[in,out] data Data to read from, always moved to currently handled character.
3990 * @param[in,out] mod Module to write to.
3991 *
3992 * @return LY_ERR values.
3993 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02003994LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02003995parse_module(struct lys_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003996{
3997 LY_ERR ret = 0;
3998 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003999 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004000 enum ly_stmt kw, prev_kw = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004001 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004002 struct lysp_submodule *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004003
4004 /* (sub)module name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004005 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004006 INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004007
Radek Krejci6d6556c2018-11-08 09:37:45 +01004008 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004009
Radek Krejcie3846472018-10-15 15:24:51 +02004010#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004011 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 +02004012
Michal Vasko7fbc8162018-09-17 10:35:16 +02004013 switch (kw) {
4014 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004015 case LY_STMT_NAMESPACE:
4016 case LY_STMT_PREFIX:
Radek Krejcie3846472018-10-15 15:24:51 +02004017 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4018 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004019 case LY_STMT_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004020 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004021 break;
4022 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004023 case LY_STMT_INCLUDE:
4024 case LY_STMT_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004025 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004026 break;
4027 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004028 case LY_STMT_ORGANIZATION:
4029 case LY_STMT_CONTACT:
4030 case LY_STMT_DESCRIPTION:
4031 case LY_STMT_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004032 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004033 break;
4034
4035 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004036 case LY_STMT_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004037 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004038 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004039 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004040 case LY_STMT_ANYDATA:
4041 case LY_STMT_ANYXML:
4042 case LY_STMT_AUGMENT:
4043 case LY_STMT_CHOICE:
4044 case LY_STMT_CONTAINER:
4045 case LY_STMT_DEVIATION:
4046 case LY_STMT_EXTENSION:
4047 case LY_STMT_FEATURE:
4048 case LY_STMT_GROUPING:
4049 case LY_STMT_IDENTITY:
4050 case LY_STMT_LEAF:
4051 case LY_STMT_LEAF_LIST:
4052 case LY_STMT_LIST:
4053 case LY_STMT_NOTIFICATION:
4054 case LY_STMT_RPC:
4055 case LY_STMT_TYPEDEF:
4056 case LY_STMT_USES:
4057 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004058 mod_stmt = Y_MOD_BODY;
4059 break;
4060 default:
4061 /* error handled in the next switch */
4062 break;
4063 }
Radek Krejcie3846472018-10-15 15:24:51 +02004064#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004065
Radek Krejcie3846472018-10-15 15:24:51 +02004066 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004067 switch (kw) {
4068 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004069 case LY_STMT_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004070 LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
4071 ctx->mod_version = mod->mod->version;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004072 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004073 case LY_STMT_NAMESPACE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004074 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 +02004075 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004076 case LY_STMT_PREFIX:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004077 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 +02004078 break;
4079
4080 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004081 case LY_STMT_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004082 LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004083 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004084 case LY_STMT_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004085 LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004086 break;
4087
4088 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004089 case LY_STMT_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004090 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 +02004091 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004092 case LY_STMT_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004093 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 +02004094 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004095 case LY_STMT_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004096 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 +02004097 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004098 case LY_STMT_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004099 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 +02004100 break;
4101
4102 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004103 case LY_STMT_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004104 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004105 break;
4106
4107 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004108 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02004109 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "module");
Radek Krejci10113652018-11-14 16:56:50 +01004110 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02004111 case LY_STMT_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004112 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004113 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004114 case LY_STMT_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004115 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004116 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004117 case LY_STMT_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004118 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004119 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004120 case LY_STMT_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004121 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004122 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004123 case LY_STMT_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004124 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004125 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004126 case LY_STMT_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004127 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004128 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004129 case LY_STMT_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004130 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004131 break;
4132
Radek Krejcid6b76452019-09-03 17:03:03 +02004133 case LY_STMT_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004134 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004135 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004136 case LY_STMT_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004137 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004138 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004139 case LY_STMT_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004140 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004141 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004142 case LY_STMT_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004143 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004144 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004145 case LY_STMT_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004146 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004147 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004148 case LY_STMT_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004149 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004150 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004151 case LY_STMT_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004152 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004153 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004154 case LY_STMT_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004155 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004156 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004157 case LY_STMT_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004158 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004159 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004160 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004161 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004162 break;
4163
4164 default:
David Sedlákb3077192019-06-19 10:55:37 +02004165 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004166 return LY_EVALID;
4167 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004168 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004169 LY_CHECK_RET(ret);
Radek Krejcie86bf772018-12-14 11:39:53 +01004170
Radek Krejci6d6556c2018-11-08 09:37:45 +01004171checks:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004172 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02004173 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004174
Michal Vasko7fbc8162018-09-17 10:35:16 +02004175 /* mandatory substatements */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004176 if (!mod->mod->ns) {
David Sedlákb3077192019-06-19 10:55:37 +02004177 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004178 return LY_EVALID;
4179 } else if (!mod->mod->prefix) {
David Sedlákb3077192019-06-19 10:55:37 +02004180 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004181 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004182 }
4183
Radek Krejcie9e987e2018-10-31 12:50:27 +01004184 /* submodules share the namespace with the module names, so there must not be
4185 * a submodule of the same name in the context, no need for revision matching */
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004186 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->mod->name, NULL);
4187 if (dup) {
David Sedlákb3077192019-06-19 10:55:37 +02004188 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 +01004189 return LY_EVALID;
4190 }
4191
4192 return ret;
4193}
4194
4195/**
4196 * @brief Parse submodule substatements.
4197 *
4198 * @param[in] ctx yang parser context for logging.
4199 * @param[in,out] data Data to read from, always moved to currently handled character.
4200 * @param[out] submod Parsed submodule structure.
4201 *
4202 * @return LY_ERR values.
4203 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02004204LY_ERR
Radek Krejcie7b95092019-05-15 11:03:07 +02004205parse_submodule(struct lys_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004206{
4207 LY_ERR ret = 0;
4208 char *buf, *word;
4209 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004210 enum ly_stmt kw, prev_kw = 0;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004211 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4212 struct lysp_submodule *dup;
4213
4214 /* submodule name */
Radek Krejcid3ca0632019-04-16 16:54:54 +02004215 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004216 INSERT_WORD(ctx, buf, submod->name, word, word_len);
4217
4218 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
4219
4220#define CHECK_ORDER(SECTION) \
David Sedlákb3077192019-06-19 10:55:37 +02004221 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 +01004222
4223 switch (kw) {
4224 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004225 case LY_STMT_BELONGS_TO:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004226 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4227 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004228 case LY_STMT_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004229 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4230 break;
4231 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004232 case LY_STMT_INCLUDE:
4233 case LY_STMT_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004234 CHECK_ORDER(Y_MOD_LINKAGE);
4235 break;
4236 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004237 case LY_STMT_ORGANIZATION:
4238 case LY_STMT_CONTACT:
4239 case LY_STMT_DESCRIPTION:
4240 case LY_STMT_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004241 CHECK_ORDER(Y_MOD_META);
4242 break;
4243
4244 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004245 case LY_STMT_REVISION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004246 CHECK_ORDER(Y_MOD_REVISION);
4247 break;
4248 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004249 case LY_STMT_ANYDATA:
4250 case LY_STMT_ANYXML:
4251 case LY_STMT_AUGMENT:
4252 case LY_STMT_CHOICE:
4253 case LY_STMT_CONTAINER:
4254 case LY_STMT_DEVIATION:
4255 case LY_STMT_EXTENSION:
4256 case LY_STMT_FEATURE:
4257 case LY_STMT_GROUPING:
4258 case LY_STMT_IDENTITY:
4259 case LY_STMT_LEAF:
4260 case LY_STMT_LEAF_LIST:
4261 case LY_STMT_LIST:
4262 case LY_STMT_NOTIFICATION:
4263 case LY_STMT_RPC:
4264 case LY_STMT_TYPEDEF:
4265 case LY_STMT_USES:
4266 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004267 mod_stmt = Y_MOD_BODY;
4268 break;
4269 default:
4270 /* error handled in the next switch */
4271 break;
4272 }
4273#undef CHECK_ORDER
4274
4275 prev_kw = kw;
4276 switch (kw) {
4277 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02004278 case LY_STMT_YANG_VERSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004279 LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
4280 ctx->mod_version = submod->version;
4281 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004282 case LY_STMT_BELONGS_TO:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004283 LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
4284 break;
4285
4286 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02004287 case LY_STMT_INCLUDE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004288 LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
4289 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004290 case LY_STMT_IMPORT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004291 LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
4292 break;
4293
4294 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02004295 case LY_STMT_ORGANIZATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004296 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
4297 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004298 case LY_STMT_CONTACT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004299 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
4300 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004301 case LY_STMT_DESCRIPTION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004302 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
4303 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004304 case LY_STMT_REFERENCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004305 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
4306 break;
4307
4308 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02004309 case LY_STMT_REVISION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004310 LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
4311 break;
4312
4313 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02004314 case LY_STMT_ANYDATA:
Radek Krejci335332a2019-09-05 13:03:35 +02004315 PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004316 /* fall through */
Radek Krejcid6b76452019-09-03 17:03:03 +02004317 case LY_STMT_ANYXML:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004318 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
4319 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004320 case LY_STMT_CHOICE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004321 LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
4322 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004323 case LY_STMT_CONTAINER:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004324 LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
4325 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004326 case LY_STMT_LEAF:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004327 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
4328 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004329 case LY_STMT_LEAF_LIST:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004330 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
4331 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004332 case LY_STMT_LIST:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004333 LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
4334 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004335 case LY_STMT_USES:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004336 LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
4337 break;
4338
Radek Krejcid6b76452019-09-03 17:03:03 +02004339 case LY_STMT_AUGMENT:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004340 LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
4341 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004342 case LY_STMT_DEVIATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004343 LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
4344 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004345 case LY_STMT_EXTENSION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004346 LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
4347 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004348 case LY_STMT_FEATURE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004349 LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
4350 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004351 case LY_STMT_GROUPING:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004352 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
4353 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004354 case LY_STMT_IDENTITY:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004355 LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
4356 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004357 case LY_STMT_NOTIFICATION:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004358 LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
4359 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004360 case LY_STMT_RPC:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004361 LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
4362 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004363 case LY_STMT_TYPEDEF:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004364 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
4365 break;
Radek Krejcid6b76452019-09-03 17:03:03 +02004366 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004367 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
4368 break;
4369
4370 default:
David Sedlákb3077192019-06-19 10:55:37 +02004371 LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004372 return LY_EVALID;
4373 }
4374 }
4375 LY_CHECK_RET(ret);
4376
4377checks:
4378 /* finalize parent pointers to the reallocated items */
David Sedlákd2ebe572019-07-22 12:53:14 +02004379 LY_CHECK_RET(lysp_parse_finalize_reallocated(ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004380
4381 /* mandatory substatements */
4382 if (!submod->belongsto) {
David Sedlákb3077192019-06-19 10:55:37 +02004383 LOGVAL_PARSER(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004384 return LY_EVALID;
4385 }
4386
4387 /* submodules share the namespace with the module names, so there must not be
4388 * a submodule of the same name in the context, no need for revision matching */
4389 dup = ly_ctx_get_submodule(ctx->ctx, NULL, submod->name, NULL);
4390 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
David Sedlákb3077192019-06-19 10:55:37 +02004391 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
Radek Krejcie9e987e2018-10-31 12:50:27 +01004392 return LY_EVALID;
4393 }
4394
Michal Vasko7fbc8162018-09-17 10:35:16 +02004395 return ret;
4396}
4397
Radek Krejcid4557c62018-09-17 11:42:09 +02004398LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02004399yang_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 +02004400{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004401 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004402 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004403 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004404 enum ly_stmt kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004405 struct lysp_submodule *mod_p = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004406
David Sedlák1b623122019-08-05 15:27:49 +02004407 /* create context */
4408 *context = calloc(1, sizeof **context);
4409 LY_CHECK_ERR_RET(!(*context), LOGMEM(ly_ctx), LY_EMEM);
4410 (*context)->ctx = ly_ctx;
Radek Krejci99435242019-09-05 16:19:15 +02004411 (*context)->pos_type = LY_VLOG_LINE;
David Sedlák1b623122019-08-05 15:27:49 +02004412 (*context)->line = 1;
4413
4414 /* map the typedefs and groupings list from main context to the submodule's context */
4415 memcpy(&(*context)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
4416 memcpy(&(*context)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
4417
Michal Vasko7fbc8162018-09-17 10:35:16 +02004418 /* "module"/"submodule" */
David Sedlák1b623122019-08-05 15:27:49 +02004419 ret = get_keyword(*context, &data, &kw, &word, &word_len);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004420 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004421
Radek Krejcid6b76452019-09-03 17:03:03 +02004422 if (kw == LY_STMT_MODULE) {
David Sedlák1b623122019-08-05 15:27:49 +02004423 LOGERR((*context)->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004424 ret = LY_EINVAL;
4425 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02004426 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02004427 LOGVAL_PARSER(*context, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004428 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004429 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004430 }
4431
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004432 mod_p = calloc(1, sizeof *mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02004433 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM((*context)->ctx), cleanup);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004434 mod_p->parsing = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004435
4436 /* substatements */
David Sedlák1b623122019-08-05 15:27:49 +02004437 ret = parse_submodule(*context, &data, mod_p);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004438 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004439
4440 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004441 while(*data && isspace(*data)) {
4442 data++;
4443 }
4444 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02004445 LOGVAL_PARSER(*context, LY_VCODE_TRAILING_SUBMOD, 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004446 ret = LY_EVALID;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004447 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004448 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004449
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004450 mod_p->parsing = 0;
4451 *submod = mod_p;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004452
Radek Krejcibbe09a92018-11-08 09:36:54 +01004453cleanup:
4454 if (ret) {
David Sedlák1b623122019-08-05 15:27:49 +02004455 lysp_submodule_free((*context)->ctx, mod_p);
4456 lys_parser_ctx_free(*context);
4457 *context = NULL;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004458 }
4459
4460 return ret;
4461}
4462
4463LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02004464yang_parse_module(struct lys_parser_ctx **context, const char *data, struct lys_module *mod)
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004465{
4466 LY_ERR ret = LY_SUCCESS;
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004467 char *word;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004468 size_t word_len;
Radek Krejcid6b76452019-09-03 17:03:03 +02004469 enum ly_stmt kw;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004470 struct lysp_module *mod_p = NULL;
4471
David Sedlák1b623122019-08-05 15:27:49 +02004472 /* create context */
4473 *context = calloc(1, sizeof **context);
4474 LY_CHECK_ERR_RET(!(*context), LOGMEM(mod->ctx), LY_EMEM);
4475 (*context)->ctx = mod->ctx;
Radek Krejci335332a2019-09-05 13:03:35 +02004476 (*context)->pos_type = LY_VLOG_LINE;
David Sedlák1b623122019-08-05 15:27:49 +02004477 (*context)->line = 1;
4478
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004479 /* "module"/"submodule" */
David Sedlák1b623122019-08-05 15:27:49 +02004480 ret = get_keyword(*context, &data, &kw, &word, &word_len);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004481 LY_CHECK_GOTO(ret, cleanup);
4482
Radek Krejcid6b76452019-09-03 17:03:03 +02004483 if (kw == LY_STMT_SUBMODULE) {
David Sedlák1b623122019-08-05 15:27:49 +02004484 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 +01004485 ret = LY_EINVAL;
4486 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02004487 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02004488 LOGVAL_PARSER((*context), LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
Radek Krejci40544fa2019-01-11 09:38:37 +01004489 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004490 goto cleanup;
4491 }
4492
4493 mod_p = calloc(1, sizeof *mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02004494 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM((*context)->ctx), cleanup);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004495 mod_p->mod = mod;
4496 mod_p->parsing = 1;
4497
4498 /* substatements */
David Sedlák1b623122019-08-05 15:27:49 +02004499 ret = parse_module(*context, &data, mod_p);
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004500 LY_CHECK_GOTO(ret, cleanup);
4501
4502 /* read some trailing spaces or new lines */
Radek Krejci0a1d0d42019-05-16 15:14:51 +02004503 while(*data && isspace(*data)) {
4504 data++;
4505 }
4506 if (*data) {
David Sedlák1538a842019-08-08 15:38:51 +02004507 LOGVAL_PARSER(*context, LY_VCODE_TRAILING_MOD, 15, data, strlen(data) > 15 ? "..." : "");
Radek Krejci40544fa2019-01-11 09:38:37 +01004508 ret = LY_EVALID;
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004509 goto cleanup;
4510 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01004511
4512 mod_p->parsing = 0;
4513 mod->parsed = mod_p;
4514
4515cleanup:
4516 if (ret) {
4517 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02004518 lys_parser_ctx_free(*context);
4519 *context = NULL;
Radek Krejcibbe09a92018-11-08 09:36:54 +01004520 }
4521
Michal Vasko7fbc8162018-09-17 10:35:16 +02004522 return ret;
4523}