blob: c4f55a6edc65c6859d238cab0f169ea01f9b4d78 [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 */
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <errno.h>
22#include <ctype.h>
23#include <string.h>
24#include <dirent.h>
25#include <assert.h>
26
27#include "common.h"
28#include "context.h"
29#include "libyang.h"
Radek Krejci70853c52018-10-15 14:46:16 +020030#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020031
32/* Macro to check YANG's yang-char grammar rule */
33#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
34 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
35 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
36 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
37 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
38 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
39 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
40 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
41 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
42 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
43
44/* These 2 macros checks YANG's identifier grammar rule */
45#define is_yangidentstartchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
46#define is_yangidentchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || \
47 c == '_' || c == '-' || c == '.')
48
Radek Krejcifaa1eac2018-10-30 14:34:55 +010049#define CHECK_UNIQUENESS(CTX, ARRAY, MEMBER, STMT, IDENT) \
50 if (ARRAY) { \
51 for (unsigned int u = 0; u < LY_ARRAY_SIZE(ARRAY) - 1; ++u) { \
52 if (!strcmp((ARRAY)[u].MEMBER, IDENT)) { \
53 LOGVAL_YANG(CTX, LY_VCODE_DUPIDENT, IDENT, STMT); \
54 return LY_EVALID; \
55 } \
56 } \
57 }
58
Radek Krejci9fcacc12018-10-11 15:59:11 +020059#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
60 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
61 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020062
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020063#define MOVE_INPUT(CTX, DATA, COUNT) (*(data))+=COUNT;(CTX)->indent+=COUNT
64
Michal Vaskoea5abea2018-09-18 13:10:54 +020065/**
66 * @brief Loop through all substatements providing, return if there are none.
67 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020068 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020069 * @param[in] DATA Raw data to read from.
70 * @param[out] KW YANG keyword read.
71 * @param[out] WORD Pointer to the keyword itself.
72 * @param[out] WORD_LEN Length of the keyword.
73 * @param[out] ERR Variable for error storing.
74 *
75 * @return In case there are no substatements or a fatal error encountered.
76 */
Radek Krejci6d6556c2018-11-08 09:37:45 +010077#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010078 LY_CHECK_RET(get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020079 if (KW == YANG_SEMICOLON) { \
Radek Krejci6d6556c2018-11-08 09:37:45 +010080 CHECKGOTO; \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010081 return LY_SUCCESS; \
Michal Vasko7fbc8162018-09-17 10:35:16 +020082 } \
83 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +020084 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020085 return LY_EVALID; \
86 } \
87 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
88 !ERR && (KW != YANG_RIGHT_BRACE); \
89 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
90
Radek Krejci6d9b9b52018-11-02 12:43:39 +010091static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
92static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
93static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
94static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
95static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
96static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +020097
Michal Vaskoea5abea2018-09-18 13:10:54 +020098/**
99 * @brief Add another character to dynamic buffer, a low-level function.
100 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200101 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200102 *
Radek Krejci404251e2018-10-09 12:06:44 +0200103 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200104 * @param[in, out] input Input string to process.
105 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200106 * @param[in,out] buf Buffer to use, can be moved by realloc().
107 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200108 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200109 *
110 * @return LY_ERR values.
111 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200112static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200113buf_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 +0200114{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200115 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200116 *buf_len += 16;
117 *buf = ly_realloc(*buf, *buf_len);
118 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
119 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200120 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200121
Radek Krejci44ceedc2018-10-02 15:54:31 +0200122 (*buf_used) += len;
123 (*input) += len;
124
Michal Vasko7fbc8162018-09-17 10:35:16 +0200125 return LY_SUCCESS;
126}
127
Michal Vaskoea5abea2018-09-18 13:10:54 +0200128/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200129 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200130 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200131 * @param[in] ctx yang parser context for logging.
132 * @param[in] c UTF8 code point of a character to check.
133 * @return LY_ERR values.
134 */
135static LY_ERR
136check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
137{
138 if (!is_yangutf8char(c)) {
139 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
140 return LY_EVALID;
141 }
142 return LY_SUCCESS;
143}
144
145/**
146 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
147 *
148 * @param[in] ctx yang parser context for logging.
149 * @param[in] c UTF8 code point of a character to check.
150 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200151 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
152 * 0 - colon not yet found (no prefix)
153 * 1 - \p c is the colon character
154 * 2 - prefix already processed, now processing the identifier
155 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200156 * If the identifier cannot be prefixed, NULL is expected.
157 * @return LY_ERR values.
158 */
159static LY_ERR
160check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
161{
162 if (first || (prefix && (*prefix) == 1)) {
163 if (!is_yangidentstartchar(c)) {
164 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
165 return LY_EVALID;
166 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200167 if (prefix) {
168 if (first) {
169 (*prefix) = 0;
170 } else {
171 (*prefix) = 2;
172 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200173 }
174 } else if (c == ':' && prefix && (*prefix) == 0) {
175 (*prefix) = 1;
176 } else if (!is_yangidentchar(c)) {
177 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
178 return LY_EVALID;
179 }
180
181 return LY_SUCCESS;
182}
183
184/**
185 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
186 *
187 * @param[in] ctx yang parser context for logging.
188 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
189 * when function returns.
190 * @param[in] arg Type of the input string to select method of checking character validity.
191 * @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 +0200192 * 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 +0200193 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
194 * @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 +0200195 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200196 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200197 *
198 * @return LY_ERR values.
199 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200200static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200201buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
202 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200203{
Radek Krejci404251e2018-10-09 12:06:44 +0200204 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200205 unsigned int c;
206 size_t len;
207
208 /* get UTF8 code point (and number of bytes coding the character) */
209 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
210 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
211 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200212 if (c == '\n') {
213 ctx->indent = 0;
214 } else {
215 /* note - even the multibyte character is count as 1 */
216 ++ctx->indent;
217 }
218
Radek Krejci44ceedc2018-10-02 15:54:31 +0200219 /* check character validity */
220 switch (arg) {
221 case Y_IDENTIF_ARG:
222 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
223 break;
224 case Y_PREF_IDENTIF_ARG:
225 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
226 break;
227 case Y_STR_ARG:
228 case Y_MAYBE_STR_ARG:
229 LY_CHECK_RET(check_stringchar(ctx, c));
230 break;
231 }
232
Michal Vasko7fbc8162018-09-17 10:35:16 +0200233 if (word_b && *word_b) {
234 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200235 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200236 return LY_EMEM;
237 }
238
239 /* in case of realloc */
240 *word_p = *word_b;
241 } else if (need_buf) {
242 /* first time we need a buffer, copy everything read up to now */
243 if (*word_len) {
244 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200245 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200246 *buf_len = *word_len;
247 memcpy(*word_b, *word_p, *word_len);
248 }
249
250 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200251 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200252 return LY_EMEM;
253 }
254
255 /* in case of realloc */
256 *word_p = *word_b;
257 } else {
258 /* just remember the first character pointer */
259 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200260 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200261 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200262 /* ... and update the word's length */
263 (*word_len) += len;
264 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200265 }
266
267 return LY_SUCCESS;
268}
269
Michal Vaskoea5abea2018-09-18 13:10:54 +0200270/**
271 * @brief Skip YANG comment in data.
272 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200273 * @param[in] ctx yang parser context for logging.
274 * @param[in,out] data Data to read from, automatically moved after the comment.
275 * @param[in] comment Type of the comment to process:
276 * 1 for a one-line comment,
277 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200278 *
279 * @return LY_ERR values.
280 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200281static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200282skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200283{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200284 /* internal statuses: 0 - comment ended,
285 * 1 - in line comment,
286 * 2 - in block comment,
287 * 3 - in block comment with last read character '*'
288 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200289 while (**data && comment) {
290 switch (comment) {
291 case 1:
292 if (**data == '\n') {
293 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200294 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200295 }
296 break;
297 case 2:
298 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200299 comment = 3;
300 } else if (**data == '\n') {
301 ++ctx->line;
302 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200303 break;
304 case 3:
305 if (**data == '/') {
306 comment = 0;
307 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200308 if (**data == '\n') {
309 ++ctx->line;
310 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200311 comment = 2;
312 }
313 break;
314 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200315 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200316 }
317
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200318 if (**data == '\n') {
319 ctx->indent = 0;
320 } else {
321 ++ctx->indent;
322 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200323 ++(*data);
324 }
325
326 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200327 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200328 return LY_EVALID;
329 }
330
331 return LY_SUCCESS;
332}
333
Michal Vaskoea5abea2018-09-18 13:10:54 +0200334/**
335 * @brief Read a quoted string from data.
336 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200337 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200338 * @param[in,out] data Data to read from, always moved to currently handled character.
339 * @param[in] arg Type of YANG keyword argument expected.
340 * @param[out] word_p Pointer to the read quoted string.
341 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
342 * set to NULL. Otherwise equal to \p word_p.
343 * @param[out] word_len Length of the read quoted string.
344 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
345 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
346 * indenation in the final quoted string.
347 *
348 * @return LY_ERR values.
349 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200350static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200351read_qstring(struct ly_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 +0200352 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200353{
354 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
355 * 4 - string finished, now skipping whitespaces looking for +,
356 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200357 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200358 const char *c;
359
360 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200361 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200362 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200363 } else {
364 assert(**data == '\'');
365 string = 1;
366 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200367 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200368
369 while (**data && string) {
370 switch (string) {
371 case 1:
372 switch (**data) {
373 case '\'':
374 /* string may be finished, but check for + */
375 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200376 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200377 break;
378 default:
379 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200380 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200381 break;
382 }
383 break;
384 case 2:
385 switch (**data) {
386 case '\"':
387 /* string may be finished, but check for + */
388 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200389 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200390 break;
391 case '\\':
392 /* special character following */
393 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200394 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200395 break;
396 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200397 if (current_indent < block_indent) {
398 ++current_indent;
399 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200400 } else {
401 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200402 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200403 }
404 break;
405 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200406 if (current_indent < block_indent) {
407 assert(need_buf);
408 current_indent += 8;
409 ctx->indent += 8;
410 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
411 /* store leftover spaces from the tab */
412 c = " ";
413 LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200414 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200415 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200416 } else {
417 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200418 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200419 /* additional characters for indentation - only 1 was count in buf_store_char */
420 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200421 }
422 break;
423 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200424 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200425 /* we will be removing the indents so we need our own buffer */
426 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200427
428 /* remove trailing tabs and spaces */
429 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
430 --(*word_len);
431 }
432
433 /* start indentation */
434 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200435 }
436
437 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200438 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
439
440 /* maintain line number */
441 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200442
443 /* reset context indentation counter for possible string after this one */
444 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200445 break;
446 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200447 /* first non-whitespace character, stop eating indentation */
448 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200449
450 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200451 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200452 break;
453 }
454 break;
455 case 3:
456 /* string encoded characters */
457 switch (**data) {
458 case 'n':
459 c = "\n";
460 break;
461 case 't':
462 c = "\t";
463 break;
464 case '\"':
465 c = *data;
466 break;
467 case '\\':
468 c = *data;
469 break;
470 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200471 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200472 return LY_EVALID;
473 }
474
475 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200476 LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200477
478 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200479 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200480 break;
481 case 4:
482 switch (**data) {
483 case '+':
484 /* string continues */
485 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200486 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200487 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200488 case '\n':
489 ++ctx->line;
490 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200491 case ' ':
492 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200493 /* just skip */
494 break;
495 default:
496 /* string is finished */
497 goto string_end;
498 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200499 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200500 break;
501 case 5:
502 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200503 case '\n':
504 ++ctx->line;
505 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200506 case ' ':
507 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200508 /* skip */
509 break;
510 case '\'':
511 string = 1;
512 break;
513 case '\"':
514 string = 2;
515 break;
516 default:
517 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200518 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200519 return LY_EVALID;
520 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200521 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200522 break;
523 default:
524 return LY_EINT;
525 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200526 }
527
528string_end:
529 return LY_SUCCESS;
530}
531
Michal Vaskoea5abea2018-09-18 13:10:54 +0200532/**
533 * @brief Get another YANG string from the raw data.
534 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200535 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200536 * @param[in,out] data Data to read from, always moved to currently handled character.
537 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200538 * @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 +0200539 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
540 * set to NULL. Otherwise equal to \p word_p.
541 * @param[out] word_len Length of the read string.
542 *
543 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200544 */
545static LY_ERR
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200546get_argument(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200547{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200548 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200549
550 /* word buffer - dynamically allocated */
551 *word_b = NULL;
552
553 /* word pointer - just a pointer to data */
554 *word_p = NULL;
555
556 *word_len = 0;
557 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200558 switch (**data) {
559 case '\'':
560 case '\"':
561 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200562 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
563 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
564 "unquoted string character, optsep, semicolon or opening brace");
565 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200566 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100567 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200568 goto str_end;
569 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200570 if ((*data)[1] == '/') {
571 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200572 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100573 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200574 } else if ((*data)[1] == '*') {
575 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200576 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100577 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200578 } else {
579 /* not a comment after all */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100580 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200581 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200582 break;
583 case ' ':
584 if (*word_len) {
585 /* word is finished */
586 goto str_end;
587 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200588 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200589 break;
590 case '\t':
591 if (*word_len) {
592 /* word is finished */
593 goto str_end;
594 }
595 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200596 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200597
598 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200599 break;
600 case '\n':
601 if (*word_len) {
602 /* word is finished */
603 goto str_end;
604 }
605 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200606 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200607
608 /* track line numbers */
609 ++ctx->line;
610
611 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200612 break;
613 case ';':
614 case '{':
615 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
616 /* word is finished */
617 goto str_end;
618 }
619
Radek Krejci44ceedc2018-10-02 15:54:31 +0200620 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200621 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200622 case '}':
623 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
624 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
625 "unquoted string character, optsep, semicolon or opening brace");
626 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200627 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200628 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200629 break;
630 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200631 }
632
633str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200634 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200635 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200636 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
637 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
638 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200639 *word_p = *word_b;
640 }
641
642 return LY_SUCCESS;
643}
644
Michal Vaskoea5abea2018-09-18 13:10:54 +0200645/**
646 * @brief Get another YANG keyword from the raw data.
647 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200648 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200649 * @param[in,out] data Data to read from, always moved to currently handled character.
650 * @param[out] kw YANG keyword read.
651 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
652 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
653 *
654 * @return LY_ERR values.
655 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200656static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200657get_keyword(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword *kw, char **word_p, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200658{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200659 int prefix;
660 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200661 unsigned int c;
662 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200663
664 if (word_p) {
665 *word_p = NULL;
666 *word_len = 0;
667 }
668
669 /* first skip "optsep", comments */
670 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200671 switch (**data) {
672 case '/':
673 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200674 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200675 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100676 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200677 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200678 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200679 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100680 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200681 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200682 /* error - not a comment after all, keyword cannot start with slash */
683 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
684 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200685 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200686 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200687 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200688 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200689 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200690 ctx->indent = 0;
691 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200692 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200693 /* skip whitespaces (optsep) */
694 ++ctx->indent;
695 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200696 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200697 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200698 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200699 break;
700 default:
701 /* either a keyword start or an invalid character */
702 goto keyword_start;
703 }
704
705 ++(*data);
706 }
707
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200708#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
709#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
710#define IF_KW_PREFIX_END }
711
Michal Vasko7fbc8162018-09-17 10:35:16 +0200712keyword_start:
713 word_start = *data;
714 *kw = YANG_NONE;
715
716 /* read the keyword itself */
717 switch (**data) {
718 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200719 MOVE_INPUT(ctx, data, 1);
720 IF_KW("rgument", 7, YANG_ARGUMENT)
721 else IF_KW("ugment", 6, YANG_AUGMENT)
722 else IF_KW("ction", 5, YANG_ACTION)
723 else IF_KW_PREFIX("ny", 2)
724 IF_KW("data", 4, YANG_ANYDATA)
725 else IF_KW("xml", 3, YANG_ANYXML)
726 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200727 break;
728 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200729 MOVE_INPUT(ctx, data, 1);
730 IF_KW("ase", 3, YANG_BASE)
731 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
732 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200733 break;
734 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200735 MOVE_INPUT(ctx, data, 1);
736 IF_KW("ase", 3, YANG_CASE)
737 else IF_KW("hoice", 5, YANG_CHOICE)
738 else IF_KW_PREFIX("on", 2)
739 IF_KW("fig", 3, YANG_CONFIG)
740 else IF_KW_PREFIX("ta", 2)
741 IF_KW("ct", 2, YANG_CONTACT)
742 else IF_KW("iner", 4, YANG_CONTAINER)
743 IF_KW_PREFIX_END
744 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200745 break;
746 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200747 MOVE_INPUT(ctx, data, 1);
748 IF_KW_PREFIX("e", 1)
749 IF_KW("fault", 5, YANG_DEFAULT)
750 else IF_KW("scription", 9, YANG_DESCRIPTION)
751 else IF_KW_PREFIX("viat", 4)
752 IF_KW("e", 1, YANG_DEVIATE)
753 else IF_KW("ion", 3, YANG_DEVIATION)
754 IF_KW_PREFIX_END
755 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200756 break;
757 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200758 MOVE_INPUT(ctx, data, 1);
759 IF_KW("num", 3, YANG_ENUM)
760 else IF_KW_PREFIX("rror-", 5)
761 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
762 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
763 IF_KW_PREFIX_END
764 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200765 break;
766 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200767 MOVE_INPUT(ctx, data, 1);
768 IF_KW("eature", 6, YANG_FEATURE)
769 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200770 break;
771 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200772 MOVE_INPUT(ctx, data, 1);
773 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200774 break;
775 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200776 MOVE_INPUT(ctx, data, 1);
777 IF_KW("dentity", 7, YANG_IDENTITY)
778 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
779 else IF_KW("mport", 5, YANG_IMPORT)
780 else IF_KW_PREFIX("n", 1)
781 IF_KW("clude", 5, YANG_INCLUDE)
782 else IF_KW("put", 3, YANG_INPUT)
783 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200784 break;
785 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200786 MOVE_INPUT(ctx, data, 1);
787 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200788 break;
789 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200790 MOVE_INPUT(ctx, data, 1);
791 IF_KW_PREFIX("e", 1)
792 IF_KW("af-list", 7, YANG_LEAF_LIST)
793 else IF_KW("af", 2, YANG_LEAF)
794 else IF_KW("ngth", 4, YANG_LENGTH)
795 IF_KW_PREFIX_END
796 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200797 break;
798 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200799 MOVE_INPUT(ctx, data, 1);
800 IF_KW_PREFIX("a", 1)
801 IF_KW("ndatory", 7, YANG_MANDATORY)
802 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
803 IF_KW_PREFIX_END
804 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
805 else IF_KW("ust", 3, YANG_MUST)
806 else IF_KW_PREFIX("od", 2)
807 IF_KW("ule", 3, YANG_MODULE)
808 else IF_KW("ifier", 5, YANG_MODIFIER)
809 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200810 break;
811 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200812 MOVE_INPUT(ctx, data, 1);
813 IF_KW("amespace", 8, YANG_NAMESPACE)
814 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200815 break;
816 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200817 MOVE_INPUT(ctx, data, 1);
818 IF_KW_PREFIX("r", 1)
819 IF_KW("dered-by", 8, YANG_ORDERED_BY)
820 else IF_KW("ganization", 10, YANG_ORGANIZATION)
821 IF_KW_PREFIX_END
822 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200823 break;
824 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200825 MOVE_INPUT(ctx, data, 1);
826 IF_KW("ath", 3, YANG_PATH)
827 else IF_KW("attern", 6, YANG_PATTERN)
828 else IF_KW("osition", 7, YANG_POSITION)
829 else IF_KW_PREFIX("re", 2)
830 IF_KW("fix", 3, YANG_PREFIX)
831 else IF_KW("sence", 5, YANG_PRESENCE)
832 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200833 break;
834 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200835 MOVE_INPUT(ctx, data, 1);
836 IF_KW("ange", 4, YANG_RANGE)
837 else IF_KW_PREFIX("e", 1)
838 IF_KW_PREFIX("f", 1)
839 IF_KW("erence", 6, YANG_REFERENCE)
840 else IF_KW("ine", 3, YANG_REFINE)
841 IF_KW_PREFIX_END
842 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
843 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
844 else IF_KW("vision", 6, YANG_REVISION)
845 IF_KW_PREFIX_END
846 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200847 break;
848 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200849 MOVE_INPUT(ctx, data, 1);
850 IF_KW("tatus", 5, YANG_STATUS)
851 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200852 break;
853 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200854 MOVE_INPUT(ctx, data, 1);
855 IF_KW("ypedef", 6, YANG_TYPEDEF)
856 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200857 break;
858 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200859 MOVE_INPUT(ctx, data, 1);
860 IF_KW_PREFIX("ni", 2)
861 IF_KW("que", 3, YANG_UNIQUE)
862 else IF_KW("ts", 2, YANG_UNITS)
863 IF_KW_PREFIX_END
864 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200865 break;
866 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200867 MOVE_INPUT(ctx, data, 1);
868 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200869 break;
870 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200871 MOVE_INPUT(ctx, data, 1);
872 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200873 break;
874 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200875 MOVE_INPUT(ctx, data, 1);
876 IF_KW("ang-version", 11, YANG_YANG_VERSION)
877 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200878 break;
879 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200880 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200881 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200882 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200883 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200884 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200885 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200886 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200887 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200888 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200889 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200890 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200891 default:
892 break;
893 }
894
895 if (*kw != YANG_NONE) {
896 /* make sure we have the whole keyword */
897 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200898 case '\n':
899 ++ctx->line;
900 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200901 case ' ':
902 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200903 /* mandatory "sep" */
904 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200905 case ':':
906 /* keyword is not actually a keyword, but prefix of an extension.
907 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
908 * and we will be checking the keyword (extension instance) itself */
909 prefix = 1;
910 MOVE_INPUT(ctx, data, 1);
911 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200912 case '{':
913 /* allowed only for input and output statements which can be without arguments */
914 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
915 break;
916 }
917 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200918 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200919 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200920 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
921 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200922 return LY_EVALID;
923 }
924 } else {
925 /* still can be an extension */
926 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200927extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200928 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200929 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
930 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200931 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200932 /* check character validity */
933 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200934 }
935 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200936 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200937 return LY_EVALID;
938 }
939
940 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200941 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200942 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200943 return LY_EVALID;
944 }
945
946 *kw = YANG_CUSTOM;
947 }
Radek Krejci626df482018-10-11 15:06:31 +0200948success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200949 if (word_p) {
950 *word_p = (char *)word_start;
951 *word_len = *data - word_start;
952 }
953
954 return LY_SUCCESS;
955}
956
Michal Vaskoea5abea2018-09-18 13:10:54 +0200957/**
958 * @brief Parse extension instance substatements.
959 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200960 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200961 * @param[in,out] data Data to read from, always moved to currently handled character.
962 * @param[in] word Extension instance substatement name (keyword).
963 * @param[in] word_len Extension instance substatement name length.
964 * @param[in,out] child Children of this extension instance to add to.
965 *
966 * @return LY_ERR values.
967 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200968static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200969parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200970 struct lysp_stmt **child)
971{
972 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100973 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200974 enum yang_keyword kw;
975 struct lysp_stmt *stmt, *par_child;
976
977 stmt = calloc(1, sizeof *stmt);
978 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
979
Radek Krejci44ceedc2018-10-02 15:54:31 +0200980 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200981
982 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100983 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200984
Radek Krejci0ae092d2018-09-20 16:43:19 +0200985 if (word) {
986 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200987 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200988 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200989 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200990 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200991 }
992
993 /* insert into parent statements */
994 if (!*child) {
995 *child = stmt;
996 } else {
997 for (par_child = *child; par_child->next; par_child = par_child->next);
998 par_child->next = stmt;
999 }
1000
Radek Krejci6d6556c2018-11-08 09:37:45 +01001001 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001002 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001003 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001004 return ret;
1005}
1006
Michal Vaskoea5abea2018-09-18 13:10:54 +02001007/**
1008 * @brief Parse extension instance.
1009 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001010 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001011 * @param[in,out] data Data to read from, always moved to currently handled character.
1012 * @param[in] ext_name Extension instance substatement name (keyword).
1013 * @param[in] ext_name_len Extension instance substatement name length.
1014 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1015 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1016 * @param[in,out] exts Extension instances to add to.
1017 *
1018 * @return LY_ERR values.
1019 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001020static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001021parse_ext(struct ly_parser_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001022 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1023{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001024 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001025 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001026 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001027 struct lysp_ext_instance *e;
1028 enum yang_keyword kw;
1029
Radek Krejci2c4e7172018-10-19 15:56:26 +02001030 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001031
1032 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001033 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001034 e->insubstmt = insubstmt;
1035 e->insubstmt_index = insubstmt_index;
1036
1037 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001038 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001039
Radek Krejci0ae092d2018-09-20 16:43:19 +02001040 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001041 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001042 }
1043
Radek Krejci6d6556c2018-11-08 09:37:45 +01001044 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001045 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001046 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001047 return ret;
1048}
1049
Michal Vaskoea5abea2018-09-18 13:10:54 +02001050/**
1051 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1052 * description, etc...
1053 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001054 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001055 * @param[in,out] data Data to read from, always moved to currently handled character.
1056 * @param[in] substmt Type of this substatement.
1057 * @param[in] substmt_index Index of this substatement.
1058 * @param[in,out] value Place to store the parsed value.
1059 * @param[in] arg Type of the YANG keyword argument (of the value).
1060 * @param[in,out] exts Extension instances to add to.
1061 *
1062 * @return LY_ERR values.
1063 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001064static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001065parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001066 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1067{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001068 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001069 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001070 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001071 enum yang_keyword kw;
1072
1073 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001074 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001075 return LY_EVALID;
1076 }
1077
1078 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001079 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001080
1081 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001082 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001083
Radek Krejci6d6556c2018-11-08 09:37:45 +01001084 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001085 switch (kw) {
1086 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001087 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001088 break;
1089 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001090 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001091 return LY_EVALID;
1092 }
1093 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001094 return ret;
1095}
1096
Michal Vaskoea5abea2018-09-18 13:10:54 +02001097/**
1098 * @brief Parse the yang-version statement.
1099 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001100 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001101 * @param[in,out] data Data to read from, always moved to currently handled character.
1102 * @param[in] mod Module to store the parsed information in.
1103 *
1104 * @return LY_ERR values.
1105 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001106static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001107parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001108{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001109 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001110 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001111 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001112 enum yang_keyword kw;
1113
1114 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001115 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001116 return LY_EVALID;
1117 }
1118
1119 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001120 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001121
1122 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1123 mod->version = LYS_VERSION_1_0;
1124 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1125 mod->version = LYS_VERSION_1_1;
1126 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001127 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001128 free(buf);
1129 return LY_EVALID;
1130 }
1131 free(buf);
1132
Radek Krejci6d6556c2018-11-08 09:37:45 +01001133 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001134 switch (kw) {
1135 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001136 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001137 break;
1138 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001139 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001140 return LY_EVALID;
1141 }
1142 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001143 return ret;
1144}
1145
Michal Vaskoea5abea2018-09-18 13:10:54 +02001146/**
1147 * @brief Parse the belongs-to statement.
1148 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001149 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001150 * @param[in,out] data Data to read from, always moved to currently handled character.
1151 * @param[in,out] belongsto Place to store the parsed value.
1152 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1153 * @param[in,out] exts Extension instances to add to.
1154 *
1155 * @return LY_ERR values.
1156 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001157static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001158parse_belongsto(struct ly_parser_ctx *ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001159{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001160 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001161 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001162 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001163 enum yang_keyword kw;
1164
1165 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001166 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001167 return LY_EVALID;
1168 }
1169
1170 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001171 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001172
Radek Krejci44ceedc2018-10-02 15:54:31 +02001173 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001174 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001175 switch (kw) {
1176 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001177 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001178 break;
1179 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001180 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001181 break;
1182 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001183 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184 return LY_EVALID;
1185 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001186 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001187 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001188checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189 /* mandatory substatements */
1190 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001191 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001192 return LY_EVALID;
1193 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001194 return ret;
1195}
1196
Michal Vaskoea5abea2018-09-18 13:10:54 +02001197/**
1198 * @brief Parse the revision-date statement.
1199 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001200 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001201 * @param[in,out] data Data to read from, always moved to currently handled character.
1202 * @param[in,out] rev Array to store the parsed value in.
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 Krejci44ceedc2018-10-02 15:54:31 +02001208parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001209{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001210 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001211 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001212 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001213 enum yang_keyword kw;
1214
1215 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001216 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001217 return LY_EVALID;
1218 }
1219
1220 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001221 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001222
1223 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001224 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001225 free(buf);
1226 return LY_EVALID;
1227 }
1228
1229 /* store value and spend buf if allocated */
1230 strncpy(rev, word, word_len);
1231 free(buf);
1232
Radek Krejci6d6556c2018-11-08 09:37:45 +01001233 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001234 switch (kw) {
1235 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001236 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001237 break;
1238 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001239 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001240 return LY_EVALID;
1241 }
1242 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001243 return ret;
1244}
1245
Michal Vaskoea5abea2018-09-18 13:10:54 +02001246/**
1247 * @brief Parse the include statement.
1248 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001249 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001250 * @param[in,out] data Data to read from, always moved to currently handled character.
1251 * @param[in,out] includes Parsed includes to add to.
1252 *
1253 * @return LY_ERR values.
1254 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001255static LY_ERR
Radek Krejcid33273d2018-10-25 14:55:52 +02001256parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001257{
Radek Krejcid33273d2018-10-25 14:55:52 +02001258 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001259 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001260 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001261 enum yang_keyword kw;
1262 struct lysp_include *inc;
1263
Radek Krejcid33273d2018-10-25 14:55:52 +02001264 LY_ARRAY_NEW_RET(ctx->ctx, mod->includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001265
1266 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001267 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001268
Radek Krejci086c7132018-10-26 15:29:04 +02001269 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1270
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001271 /* submodules share the namespace with the module names, so there must not be
1272 * a module of the same name in the context, no need for revision matching */
1273 if (!strcmp(ctx->mod->name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
1274 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1275 return LY_EVALID;
1276 }
1277
Radek Krejci6d6556c2018-11-08 09:37:45 +01001278 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001279 switch (kw) {
1280 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001281 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 +02001282 break;
1283 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001284 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 +02001285 break;
1286 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001287 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001288 break;
1289 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001290 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001291 break;
1292 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001293 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001294 return LY_EVALID;
1295 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001296 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001297 return ret;
1298}
1299
Michal Vaskoea5abea2018-09-18 13:10:54 +02001300/**
1301 * @brief Parse the import statement.
1302 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001303 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001304 * @param[in,out] data Data to read from, always moved to currently handled character.
1305 * @param[in,out] imports Parsed imports to add to.
1306 *
1307 * @return LY_ERR values.
1308 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001309static LY_ERR
Radek Krejci70853c52018-10-15 14:46:16 +02001310parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *module)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001311{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001312 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001313 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001314 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001315 enum yang_keyword kw;
1316 struct lysp_import *imp;
1317
Radek Krejci2c4e7172018-10-19 15:56:26 +02001318 LY_ARRAY_NEW_RET(ctx->ctx, module->imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001319
1320 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001321 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001322 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001323
Radek Krejci6d6556c2018-11-08 09:37:45 +01001324 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001325 switch (kw) {
1326 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001327 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
Radek Krejci70853c52018-10-15 14:46:16 +02001328 LY_CHECK_RET(lysp_check_prefix(ctx, module, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001329 break;
1330 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001331 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 +02001332 break;
1333 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001334 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 +02001335 break;
1336 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001337 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001338 break;
1339 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001340 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001341 break;
1342 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001343 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001344 return LY_EVALID;
1345 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001346 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001347 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001348checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001349 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001350 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001351
1352 return ret;
1353}
1354
Michal Vaskoea5abea2018-09-18 13:10:54 +02001355/**
1356 * @brief Parse the revision statement.
1357 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001358 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001359 * @param[in,out] data Data to read from, always moved to currently handled character.
1360 * @param[in,out] revs Parsed revisions to add to.
1361 *
1362 * @return LY_ERR values.
1363 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001364static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001365parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001366{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001367 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001368 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001369 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001370 enum yang_keyword kw;
1371 struct lysp_revision *rev;
1372
Radek Krejci2c4e7172018-10-19 15:56:26 +02001373 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001374
1375 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001376 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001377
1378 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001379 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001380 return LY_EVALID;
1381 }
1382
Radek Krejcib7db73a2018-10-24 14:18:40 +02001383 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001384 free(buf);
1385
Radek Krejci6d6556c2018-11-08 09:37:45 +01001386 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001387 switch (kw) {
1388 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001389 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 +02001390 break;
1391 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001392 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 +02001393 break;
1394 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001395 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001396 break;
1397 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001398 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001399 return LY_EVALID;
1400 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001401 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001402 return ret;
1403}
1404
Michal Vaskoea5abea2018-09-18 13:10:54 +02001405/**
1406 * @brief Parse a generic text field that can have more instances such as base.
1407 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001408 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001409 * @param[in,out] data Data to read from, always moved to currently handled character.
1410 * @param[in] substmt Type of this substatement.
1411 * @param[in,out] texts Parsed values to add to.
1412 * @param[in] arg Type of the expected argument.
1413 * @param[in,out] exts Extension instances to add to.
1414 *
1415 * @return LY_ERR values.
1416 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001417static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001418parse_text_fields(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001419 struct lysp_ext_instance **exts)
1420{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001421 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001422 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001423 const char **item;
1424 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001425 enum yang_keyword kw;
1426
1427 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001428 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001429
1430 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001431 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001432
Radek Krejci151a5b72018-10-19 14:21:44 +02001433 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001434 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001435 switch (kw) {
1436 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001437 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438 break;
1439 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001440 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001441 return LY_EVALID;
1442 }
1443 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001444 return ret;
1445}
1446
Michal Vaskoea5abea2018-09-18 13:10:54 +02001447/**
1448 * @brief Parse the config statement.
1449 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001450 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001451 * @param[in,out] data Data to read from, always moved to currently handled character.
1452 * @param[in,out] flags Flags to add to.
1453 * @param[in,out] exts Extension instances to add to.
1454 *
1455 * @return LY_ERR values.
1456 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001457static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001458parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001459{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001460 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001461 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001462 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001463 enum yang_keyword kw;
1464
1465 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001466 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001467 return LY_EVALID;
1468 }
1469
1470 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001471 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001472
1473 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1474 *flags |= LYS_CONFIG_W;
1475 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1476 *flags |= LYS_CONFIG_R;
1477 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001478 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001479 free(buf);
1480 return LY_EVALID;
1481 }
1482 free(buf);
1483
Radek Krejci6d6556c2018-11-08 09:37:45 +01001484 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001485 switch (kw) {
1486 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001487 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001488 break;
1489 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001490 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001491 return LY_EVALID;
1492 }
1493 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001494 return ret;
1495}
1496
Michal Vaskoea5abea2018-09-18 13:10:54 +02001497/**
1498 * @brief Parse the mandatory statement.
1499 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001500 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001501 * @param[in,out] data Data to read from, always moved to currently handled character.
1502 * @param[in,out] flags Flags to add to.
1503 * @param[in,out] exts Extension instances to add to.
1504 *
1505 * @return LY_ERR values.
1506 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001507static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001508parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001509{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001510 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001511 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001512 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001513 enum yang_keyword kw;
1514
1515 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001516 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001517 return LY_EVALID;
1518 }
1519
1520 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001521 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001522
1523 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1524 *flags |= LYS_MAND_TRUE;
1525 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1526 *flags |= LYS_MAND_FALSE;
1527 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001528 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001529 free(buf);
1530 return LY_EVALID;
1531 }
1532 free(buf);
1533
Radek Krejci6d6556c2018-11-08 09:37:45 +01001534 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001535 switch (kw) {
1536 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001537 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001538 break;
1539 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001540 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001541 return LY_EVALID;
1542 }
1543 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001544 return ret;
1545}
1546
Michal Vaskoea5abea2018-09-18 13:10:54 +02001547/**
1548 * @brief Parse a restriction such as range or length.
1549 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001550 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001551 * @param[in,out] data Data to read from, always moved to currently handled character.
1552 * @param[in] restr_kw Type of this particular restriction.
1553 * @param[in,out] exts Extension instances to add to.
1554 *
1555 * @return LY_ERR values.
1556 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001557static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001558parse_restr(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr *restr)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001559{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001560 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001561 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001562 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001563 enum yang_keyword kw;
1564
1565 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001566 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001567
Radek Krejci44ceedc2018-10-02 15:54:31 +02001568 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001569 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001570 switch (kw) {
1571 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001572 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 +02001573 break;
1574 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001575 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 +02001576 break;
1577 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001578 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 +02001579 break;
1580 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001581 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 +02001582 break;
1583 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001584 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001585 break;
1586 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001587 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001588 return LY_EVALID;
1589 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001590 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001591 return ret;
1592}
1593
Michal Vaskoea5abea2018-09-18 13:10:54 +02001594/**
1595 * @brief Parse a restriction that can have more instances such as must.
1596 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001597 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001598 * @param[in,out] data Data to read from, always moved to currently handled character.
1599 * @param[in] restr_kw Type of this particular restriction.
1600 * @param[in,out] restrs Restrictions to add to.
1601 *
1602 * @return LY_ERR values.
1603 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001604static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001605parse_restrs(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword restr_kw, struct lysp_restr **restrs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001606{
1607 struct lysp_restr *restr;
1608
Radek Krejci2c4e7172018-10-19 15:56:26 +02001609 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001610 return parse_restr(ctx, data, restr_kw, restr);
1611}
1612
Michal Vaskoea5abea2018-09-18 13:10:54 +02001613/**
1614 * @brief Parse the status statement.
1615 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001616 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001617 * @param[in,out] data Data to read from, always moved to currently handled character.
1618 * @param[in,out] flags Flags to add to.
1619 * @param[in,out] exts Extension instances to add to.
1620 *
1621 * @return LY_ERR values.
1622 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001623static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001624parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001625{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001626 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001627 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001628 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001629 enum yang_keyword kw;
1630
1631 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001632 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001633 return LY_EVALID;
1634 }
1635
1636 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001637 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001638
1639 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1640 *flags |= LYS_STATUS_CURR;
1641 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1642 *flags |= LYS_STATUS_DEPRC;
1643 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1644 *flags |= LYS_STATUS_OBSLT;
1645 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001646 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001647 free(buf);
1648 return LY_EVALID;
1649 }
1650 free(buf);
1651
Radek Krejci6d6556c2018-11-08 09:37:45 +01001652 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001653 switch (kw) {
1654 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001655 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001656 break;
1657 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001658 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001659 return LY_EVALID;
1660 }
1661 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001662 return ret;
1663}
1664
Michal Vaskoea5abea2018-09-18 13:10:54 +02001665/**
1666 * @brief Parse the when statement.
1667 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001668 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001669 * @param[in,out] data Data to read from, always moved to currently handled character.
1670 * @param[in,out] when_p When pointer to parse to.
1671 *
1672 * @return LY_ERR values.
1673 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001674static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001675parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001676{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001677 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001678 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001679 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001680 enum yang_keyword kw;
1681 struct lysp_when *when;
1682
1683 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001684 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001685 return LY_EVALID;
1686 }
1687
1688 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001689 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001690 *when_p = when;
1691
1692 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001693 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001694 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001695
Radek Krejci6d6556c2018-11-08 09:37:45 +01001696 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001697 switch (kw) {
1698 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001699 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 +02001700 break;
1701 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001702 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 +02001703 break;
1704 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001705 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001706 break;
1707 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001708 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001709 return LY_EVALID;
1710 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001711 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001712 return ret;
1713}
1714
Michal Vaskoea5abea2018-09-18 13:10:54 +02001715/**
1716 * @brief Parse the anydata or anyxml statement.
1717 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001718 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001719 * @param[in,out] data Data to read from, always moved to currently handled character.
1720 * @param[in] kw Type of this particular keyword.
1721 * @param[in,out] siblings Siblings to add to.
1722 *
1723 * @return LY_ERR values.
1724 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001725static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001726parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001727{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001728 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001729 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001730 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001731 struct lysp_node *iter;
1732 struct lysp_node_anydata *any;
1733
1734 /* create structure */
1735 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001736 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001737 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001738 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001739
1740 /* insert into siblings */
1741 if (!*siblings) {
1742 *siblings = (struct lysp_node *)any;
1743 } else {
1744 for (iter = *siblings; iter->next; iter = iter->next);
1745 iter->next = (struct lysp_node *)any;
1746 }
1747
1748 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001749 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001750 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001751
1752 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001753 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001754 switch (kw) {
1755 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001756 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001757 break;
1758 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001759 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 +02001760 break;
1761 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001762 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 +02001763 break;
1764 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001765 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001766 break;
1767 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001768 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001769 break;
1770 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001771 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 +02001772 break;
1773 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001774 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001775 break;
1776 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001777 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001778 break;
1779 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001780 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001781 break;
1782 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001783 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001784 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001785 return LY_EVALID;
1786 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001787 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001788 return ret;
1789}
1790
Michal Vaskoea5abea2018-09-18 13:10:54 +02001791/**
1792 * @brief Parse the value or position statement. Substatement of type enum statement.
1793 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001794 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001795 * @param[in,out] data Data to read from, always moved to currently handled character.
1796 * @param[in] val_kw Type of this particular keyword.
1797 * @param[in,out] value Value to write to.
1798 * @param[in,out] flags Flags to write to.
1799 * @param[in,out] exts Extension instances to add to.
1800 *
1801 * @return LY_ERR values.
1802 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001803static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001804parse_type_enum_value_pos(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword val_kw, int64_t *value, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001805 struct lysp_ext_instance **exts)
1806{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001807 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001808 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001809 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001810 long int num;
1811 unsigned long int unum;
1812 enum yang_keyword kw;
1813
1814 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001815 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001816 return LY_EVALID;
1817 }
1818 *flags |= LYS_SET_VALUE;
1819
1820 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001821 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001822
1823 if (!word_len || (word[0] == '+') || ((word[0] == '0') && (word_len > 1)) || ((val_kw == YANG_VALUE) && !strncmp(word, "-0", 2))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001824 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001825 free(buf);
1826 return LY_EVALID;
1827 }
1828
1829 errno = 0;
1830 if (val_kw == YANG_VALUE) {
1831 num = strtol(word, &ptr, 10);
1832 } else {
1833 unum = strtoul(word, &ptr, 10);
1834 }
1835 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001836 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001837 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001838 free(buf);
1839 return LY_EVALID;
1840 }
1841 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001842 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001843 free(buf);
1844 return LY_EVALID;
1845 }
1846 if (val_kw == YANG_VALUE) {
1847 *value = num;
1848 } else {
1849 *value = unum;
1850 }
1851 free(buf);
1852
Radek Krejci6d6556c2018-11-08 09:37:45 +01001853 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001854 switch (kw) {
1855 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001856 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, val_kw == YANG_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001857 break;
1858 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001859 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001860 return LY_EVALID;
1861 }
1862 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001863 return ret;
1864}
1865
Michal Vaskoea5abea2018-09-18 13:10:54 +02001866/**
1867 * @brief Parse the enum or bit statement. Substatement of type statement.
1868 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001869 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001870 * @param[in,out] data Data to read from, always moved to currently handled character.
1871 * @param[in] enum_kw Type of this particular keyword.
1872 * @param[in,out] enums Enums or bits to add to.
1873 *
1874 * @return LY_ERR values.
1875 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001876static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001877parse_type_enum(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword enum_kw, struct lysp_type_enum **enums)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001878{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001879 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001880 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001881 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001882 enum yang_keyword kw;
1883 struct lysp_type_enum *enm;
1884
Radek Krejci2c4e7172018-10-19 15:56:26 +02001885 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001886
1887 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001888 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001889 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001890
Radek Krejci6d6556c2018-11-08 09:37:45 +01001891 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001892 switch (kw) {
1893 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001894 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 +02001895 break;
1896 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001897 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 +02001898 break;
1899 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001900 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 +02001901 break;
1902 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001903 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001904 break;
1905 case YANG_VALUE:
1906 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001907 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001908 break;
1909 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001910 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001911 break;
1912 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001913 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001914 return LY_EVALID;
1915 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001916 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001917 return ret;
1918}
1919
Michal Vaskoea5abea2018-09-18 13:10:54 +02001920/**
1921 * @brief Parse the fraction-digits statement. Substatement of type statement.
1922 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001923 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001924 * @param[in,out] data Data to read from, always moved to currently handled character.
1925 * @param[in,out] fracdig Value to write to.
1926 * @param[in,out] exts Extension instances to add to.
1927 *
1928 * @return LY_ERR values.
1929 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001930static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001931parse_type_fracdigits(struct ly_parser_ctx *ctx, const char **data, uint8_t *fracdig, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001932{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001933 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001934 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001935 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001936 unsigned long int num;
1937 enum yang_keyword kw;
1938
1939 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001940 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001941 return LY_EVALID;
1942 }
1943
1944 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001945 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001946
1947 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001948 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001949 free(buf);
1950 return LY_EVALID;
1951 }
1952
1953 errno = 0;
1954 num = strtoul(word, &ptr, 10);
1955 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001956 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001957 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001958 free(buf);
1959 return LY_EVALID;
1960 }
1961 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001962 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001963 free(buf);
1964 return LY_EVALID;
1965 }
1966 *fracdig = num;
1967 free(buf);
1968
Radek Krejci6d6556c2018-11-08 09:37:45 +01001969 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001970 switch (kw) {
1971 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001972 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001973 break;
1974 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001975 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001976 return LY_EVALID;
1977 }
1978 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001979 return ret;
1980}
1981
Michal Vaskoea5abea2018-09-18 13:10:54 +02001982/**
1983 * @brief Parse the require-instance statement. Substatement of type statement.
1984 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001985 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001986 * @param[in,out] data Data to read from, always moved to currently handled character.
1987 * @param[in,out] reqinst Value to write to.
1988 * @param[in,out] flags Flags to write to.
1989 * @param[in,out] exts Extension instances to add to.
1990 *
1991 * @return LY_ERR values.
1992 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001993static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001994parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001995 struct lysp_ext_instance **exts)
1996{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001997 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001998 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001999 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002000 enum yang_keyword kw;
2001
2002 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002003 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002004 return LY_EVALID;
2005 }
2006 *flags |= LYS_SET_REQINST;
2007
2008 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002009 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002010
2011 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2012 *reqinst = 1;
2013 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002014 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002015 free(buf);
2016 return LY_EVALID;
2017 }
2018 free(buf);
2019
Radek Krejci6d6556c2018-11-08 09:37:45 +01002020 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002021 switch (kw) {
2022 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002023 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002024 break;
2025 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002026 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002027 return LY_EVALID;
2028 }
2029 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002030 return ret;
2031}
2032
Michal Vaskoea5abea2018-09-18 13:10:54 +02002033/**
2034 * @brief Parse the modifier statement. Substatement of type pattern statement.
2035 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002036 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002037 * @param[in,out] data Data to read from, always moved to currently handled character.
2038 * @param[in,out] pat Value to write to.
2039 * @param[in,out] exts Extension instances to add to.
2040 *
2041 * @return LY_ERR values.
2042 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002043static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002044parse_type_pattern_modifier(struct ly_parser_ctx *ctx, const char **data, const char **pat, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002045{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002046 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002047 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002048 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002049 enum yang_keyword kw;
2050
2051 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002052 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002053 return LY_EVALID;
2054 }
2055
2056 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002057 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002058
2059 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002060 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002061 free(buf);
2062 return LY_EVALID;
2063 }
2064 free(buf);
2065
2066 /* replace the value in the dictionary */
2067 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002068 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002069 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002070 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002071
2072 assert(buf[0] == 0x06);
2073 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002074 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002075
Radek Krejci6d6556c2018-11-08 09:37:45 +01002076 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002077 switch (kw) {
2078 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002079 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002080 break;
2081 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002082 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002083 return LY_EVALID;
2084 }
2085 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002086 return ret;
2087}
2088
Michal Vaskoea5abea2018-09-18 13:10:54 +02002089/**
2090 * @brief Parse the pattern statement. Substatement of type statement.
2091 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002092 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002093 * @param[in,out] data Data to read from, always moved to currently handled character.
2094 * @param[in,out] patterns Restrictions to add to.
2095 *
2096 * @return LY_ERR values.
2097 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002098static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002099parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002100{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002101 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002102 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002103 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002104 enum yang_keyword kw;
2105 struct lysp_restr *restr;
2106
Radek Krejci2c4e7172018-10-19 15:56:26 +02002107 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002108
2109 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002110 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002111
2112 /* add special meaning first byte */
2113 if (buf) {
2114 buf = realloc(buf, word_len + 2);
2115 word = buf;
2116 } else {
2117 buf = malloc(word_len + 2);
2118 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002119 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002120 memmove(buf + 1, word, word_len);
2121 buf[0] = 0x06; /* pattern's default regular-match flag */
2122 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2123 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002124
Radek Krejci6d6556c2018-11-08 09:37:45 +01002125 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002126 switch (kw) {
2127 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002128 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 +02002129 break;
2130 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002131 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 +02002132 break;
2133 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002134 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 +02002135 break;
2136 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002137 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 +02002138 break;
2139 case YANG_MODIFIER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002140 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002141 break;
2142 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002143 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002144 break;
2145 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002146 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002147 return LY_EVALID;
2148 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002149 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002150 return ret;
2151}
2152
Michal Vaskoea5abea2018-09-18 13:10:54 +02002153/**
2154 * @brief Parse the type statement.
2155 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002156 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002157 * @param[in,out] data Data to read from, always moved to currently handled character.
2158 * @param[in,out] type Type to wrote to.
2159 *
2160 * @return LY_ERR values.
2161 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002162static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002163parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002164{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002165 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002166 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002167 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002168 enum yang_keyword kw;
2169 struct lysp_type *nest_type;
2170
2171 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002172 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002173 return LY_EVALID;
2174 }
2175
2176 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002177 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002178 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002179
Radek Krejci6d6556c2018-11-08 09:37:45 +01002180 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002181 switch (kw) {
2182 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002183 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 +01002184 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002185 break;
2186 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002187 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002188 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189 break;
2190 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002191 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002192 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002193 break;
2194 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002195 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002196 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002197 break;
2198 case YANG_LENGTH:
2199 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002200 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002201 return LY_EVALID;
2202 }
2203 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002204 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002205
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002206 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002207 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002208 break;
2209 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002210 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 +01002211 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002212 break;
2213 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002214 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002215 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002216 break;
2217 case YANG_RANGE:
2218 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002219 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002220 return LY_EVALID;
2221 }
2222 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002223 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002224
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002225 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002226 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002227 break;
2228 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002229 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002230 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002231 break;
2232 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002233 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2234 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002235 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002236 break;
2237 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002238 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002239 break;
2240 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002241 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002242 return LY_EVALID;
2243 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002244 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002245 return ret;
2246}
2247
Michal Vaskoea5abea2018-09-18 13:10:54 +02002248/**
2249 * @brief Parse the leaf statement.
2250 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002251 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002252 * @param[in,out] data Data to read from, always moved to currently handled character.
2253 * @param[in,out] siblings Siblings to add to.
2254 *
2255 * @return LY_ERR values.
2256 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002257static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002258parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002259{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002260 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002261 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002262 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002263 enum yang_keyword kw;
2264 struct lysp_node *iter;
2265 struct lysp_node_leaf *leaf;
2266
2267 /* create structure */
2268 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002269 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002270 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002271 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002272
2273 /* insert into siblings */
2274 if (!*siblings) {
2275 *siblings = (struct lysp_node *)leaf;
2276 } else {
2277 for (iter = *siblings; iter->next; iter = iter->next);
2278 iter->next = (struct lysp_node *)leaf;
2279 }
2280
2281 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002282 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002283 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002284
2285 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002286 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002287 switch (kw) {
2288 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002289 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002290 break;
2291 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002292 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 +02002293 break;
2294 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002295 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 +02002296 break;
2297 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002298 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 +02002299 break;
2300 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002301 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002302 break;
2303 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002304 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002305 break;
2306 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002307 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 +02002308 break;
2309 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002310 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002311 break;
2312 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002313 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002314 break;
2315 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002316 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 +02002317 break;
2318 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002319 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002320 break;
2321 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002322 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002323 break;
2324 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002325 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002326 return LY_EVALID;
2327 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002328 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002329 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002330checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002331 /* mandatory substatements */
2332 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002333 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002334 return LY_EVALID;
2335 }
2336
2337 return ret;
2338}
2339
Michal Vaskoea5abea2018-09-18 13:10:54 +02002340/**
2341 * @brief Parse the max-elements statement.
2342 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002343 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002344 * @param[in,out] data Data to read from, always moved to currently handled character.
2345 * @param[in,out] max Value to write to.
2346 * @param[in,out] flags Flags to write to.
2347 * @param[in,out] exts Extension instances to add to.
2348 *
2349 * @return LY_ERR values.
2350 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002351static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002352parse_maxelements(struct ly_parser_ctx *ctx, const char **data, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002353{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002354 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002355 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002356 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002357 unsigned long int num;
2358 enum yang_keyword kw;
2359
2360 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002361 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002362 return LY_EVALID;
2363 }
2364 *flags |= LYS_SET_MAX;
2365
2366 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002367 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002368
2369 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002370 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002371 free(buf);
2372 return LY_EVALID;
2373 }
2374
2375 if (strncmp(word, "unbounded", word_len)) {
2376 errno = 0;
2377 num = strtoul(word, &ptr, 10);
2378 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002379 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002380 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002381 free(buf);
2382 return LY_EVALID;
2383 }
2384 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002385 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002386 free(buf);
2387 return LY_EVALID;
2388 }
2389
2390 *max = num;
2391 }
2392 free(buf);
2393
Radek Krejci6d6556c2018-11-08 09:37:45 +01002394 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002395 switch (kw) {
2396 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002397 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002398 break;
2399 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002400 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002401 return LY_EVALID;
2402 }
2403 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002404 return ret;
2405}
2406
Michal Vaskoea5abea2018-09-18 13:10:54 +02002407/**
2408 * @brief Parse the min-elements statement.
2409 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002410 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002411 * @param[in,out] data Data to read from, always moved to currently handled character.
2412 * @param[in,out] min Value to write to.
2413 * @param[in,out] flags Flags to write to.
2414 * @param[in,out] exts Extension instances to add to.
2415 *
2416 * @return LY_ERR values.
2417 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002418static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002419parse_minelements(struct ly_parser_ctx *ctx, const char **data, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002420{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002421 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002422 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002423 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002424 unsigned long int num;
2425 enum yang_keyword kw;
2426
2427 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002428 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002429 return LY_EVALID;
2430 }
2431 *flags |= LYS_SET_MIN;
2432
2433 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002434 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002435
2436 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002437 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002438 free(buf);
2439 return LY_EVALID;
2440 }
2441
2442 errno = 0;
2443 num = strtoul(word, &ptr, 10);
2444 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002445 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002446 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002447 free(buf);
2448 return LY_EVALID;
2449 }
2450 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002451 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002452 free(buf);
2453 return LY_EVALID;
2454 }
2455 *min = num;
2456 free(buf);
2457
Radek Krejci6d6556c2018-11-08 09:37:45 +01002458 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002459 switch (kw) {
2460 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002461 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002462 break;
2463 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002464 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002465 return LY_EVALID;
2466 }
2467 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002468 return ret;
2469}
2470
Michal Vaskoea5abea2018-09-18 13:10:54 +02002471/**
2472 * @brief Parse the ordered-by statement.
2473 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002474 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002475 * @param[in,out] data Data to read from, always moved to currently handled character.
2476 * @param[in,out] flags Flags to write to.
2477 * @param[in,out] exts Extension instances to add to.
2478 *
2479 * @return LY_ERR values.
2480 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002481static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002482parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002483{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002484 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002485 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002486 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002487 enum yang_keyword kw;
2488
2489 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002490 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002491 return LY_EVALID;
2492 }
2493
2494 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002495 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002496
2497 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2498 *flags |= LYS_ORDBY_SYSTEM;
2499 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2500 *flags |= LYS_ORDBY_USER;
2501 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002502 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002503 free(buf);
2504 return LY_EVALID;
2505 }
2506 free(buf);
2507
Radek Krejci6d6556c2018-11-08 09:37:45 +01002508 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002509 switch (kw) {
2510 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002511 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002512 break;
2513 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002514 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002515 return LY_EVALID;
2516 }
2517 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002518 return ret;
2519}
2520
Michal Vaskoea5abea2018-09-18 13:10:54 +02002521/**
2522 * @brief Parse the leaf-list statement.
2523 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002524 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002525 * @param[in,out] data Data to read from, always moved to currently handled character.
2526 * @param[in,out] siblings Siblings to add to.
2527 *
2528 * @return LY_ERR values.
2529 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002530static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002531parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002532{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002533 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002534 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002535 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002536 enum yang_keyword kw;
2537 struct lysp_node *iter;
2538 struct lysp_node_leaflist *llist;
2539
2540 /* create structure */
2541 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002542 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002543 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002544 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002545
2546 /* insert into siblings */
2547 if (!*siblings) {
2548 *siblings = (struct lysp_node *)llist;
2549 } else {
2550 for (iter = *siblings; iter->next; iter = iter->next);
2551 iter->next = (struct lysp_node *)llist;
2552 }
2553
2554 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002555 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002556 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002557
2558 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002559 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002560 switch (kw) {
2561 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002562 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002563 break;
2564 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002565 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 +02002566 break;
2567 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002568 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 +02002569 break;
2570 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002571 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 +02002572 break;
2573 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002574 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002575 break;
2576 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002577 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002578 break;
2579 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002580 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002581 break;
2582 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002583 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002584 break;
2585 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002586 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 +02002587 break;
2588 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002589 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002590 break;
2591 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002592 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002593 break;
2594 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002595 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 +02002596 break;
2597 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002598 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002599 break;
2600 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002601 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002602 break;
2603 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002604 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002605 return LY_EVALID;
2606 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002607 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002608 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002609checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002610 /* mandatory substatements */
2611 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002612 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002613 return LY_EVALID;
2614 }
2615
2616 return ret;
2617}
2618
Michal Vaskoea5abea2018-09-18 13:10:54 +02002619/**
2620 * @brief Parse the refine statement.
2621 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002622 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002623 * @param[in,out] data Data to read from, always moved to currently handled character.
2624 * @param[in,out] refines Refines to add to.
2625 *
2626 * @return LY_ERR values.
2627 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002628static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002629parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002630{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002631 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002632 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002633 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002634 enum yang_keyword kw;
2635 struct lysp_refine *rf;
2636
Radek Krejci2c4e7172018-10-19 15:56:26 +02002637 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002638
2639 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002640 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002641 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002642
Radek Krejci6d6556c2018-11-08 09:37:45 +01002643 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002644 switch (kw) {
2645 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002646 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002647 break;
2648 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002649 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 +02002650 break;
2651 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002652 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 +02002653 break;
2654 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002655 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 +02002656 break;
2657 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002658 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002659 break;
2660 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002661 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002662 break;
2663 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002664 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002665 break;
2666 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002667 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002668 break;
2669 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002670 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 +02002671 break;
2672 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002673 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 +02002674 break;
2675 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002676 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002677 break;
2678 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002679 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002680 return LY_EVALID;
2681 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002682 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002683 return ret;
2684}
2685
Michal Vaskoea5abea2018-09-18 13:10:54 +02002686/**
2687 * @brief Parse the typedef statement.
2688 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002689 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002690 * @param[in,out] data Data to read from, always moved to currently handled character.
2691 * @param[in,out] typedefs Typedefs to add to.
2692 *
2693 * @return LY_ERR values.
2694 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002695static LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01002696parse_typedef(struct ly_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002697{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002698 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002699 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002700 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002701 enum yang_keyword kw;
2702 struct lysp_tpdf *tpdf;
2703
Radek Krejci2c4e7172018-10-19 15:56:26 +02002704 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002705
2706 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002707 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002708 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002709
2710 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002711 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002712 switch (kw) {
2713 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002714 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 +02002715 break;
2716 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002717 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 +02002718 break;
2719 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002720 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 +02002721 break;
2722 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002723 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002724 break;
2725 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002726 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002727 break;
2728 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002729 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 +02002730 break;
2731 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002732 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002733 break;
2734 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002735 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002736 return LY_EVALID;
2737 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002738 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002739 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002740checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002741 /* mandatory substatements */
2742 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002743 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002744 return LY_EVALID;
2745 }
2746
Radek Krejcibbe09a92018-11-08 09:36:54 +01002747 /* store data for collision check */
2748 if (parent) {
2749 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2750 }
2751
Michal Vasko7fbc8162018-09-17 10:35:16 +02002752 return ret;
2753}
2754
Michal Vaskoea5abea2018-09-18 13:10:54 +02002755/**
2756 * @brief Parse the input or output statement.
2757 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002758 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002759 * @param[in,out] data Data to read from, always moved to currently handled character.
2760 * @param[in] kw Type of this particular keyword
2761 * @param[in,out] inout_p Input/output pointer to write to.
2762 *
2763 * @return LY_ERR values.
2764 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002765static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002766parse_inout(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node *parent, struct lysp_action_inout **inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002767{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002768 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002769 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002770 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002771 struct lysp_action_inout *inout;
2772
2773 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002774 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002775 return LY_EVALID;
2776 }
2777
2778 /* create structure */
2779 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002780 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002781 *inout_p = inout;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002782 inout->nodetype = LYS_INOUT;
2783 inout->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002784
2785 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002786 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002787 switch (kw) {
2788 case YANG_ANYDATA:
2789 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002790 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002791 break;
2792 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002793 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002794 break;
2795 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002796 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002797 break;
2798 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002799 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002800 break;
2801 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002802 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002803 break;
2804 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002805 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002806 break;
2807 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002808 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002809 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002810 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002811 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout, data, &inout->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002812 break;
2813 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002814 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002815 break;
2816 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002817 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout, &inout->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002818 break;
2819 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002820 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002821 break;
2822 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002823 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002824 return LY_EVALID;
2825 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002826 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002827 return ret;
2828}
2829
Michal Vaskoea5abea2018-09-18 13:10:54 +02002830/**
2831 * @brief Parse the action statement.
2832 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002833 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002834 * @param[in,out] data Data to read from, always moved to currently handled character.
2835 * @param[in,out] actions Actions to add to.
2836 *
2837 * @return LY_ERR values.
2838 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002839static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002840parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002841{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002842 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002843 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002844 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002845 enum yang_keyword kw;
2846 struct lysp_action *act;
2847
Radek Krejci2c4e7172018-10-19 15:56:26 +02002848 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002849
2850 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002851 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002852 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002853 act->nodetype = LYS_ACTION;
2854 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002855
Radek Krejci6d6556c2018-11-08 09:37:45 +01002856 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 switch (kw) {
2858 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002859 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 +02002860 break;
2861 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002862 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 +02002863 break;
2864 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002865 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 +02002866 break;
2867 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002868 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002869 break;
2870
2871 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002872 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002873 break;
2874 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002875 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002876 break;
2877
2878 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002879 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002880 break;
2881 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002882 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002883 break;
2884 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002885 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002886 break;
2887 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002888 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002889 return LY_EVALID;
2890 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002891 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002892 return ret;
2893}
2894
Michal Vaskoea5abea2018-09-18 13:10:54 +02002895/**
2896 * @brief Parse the notification statement.
2897 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002898 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002899 * @param[in,out] data Data to read from, always moved to currently handled character.
2900 * @param[in,out] notifs Notifications to add to.
2901 *
2902 * @return LY_ERR values.
2903 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002904static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002905parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002906{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002907 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002908 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002909 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002910 enum yang_keyword kw;
2911 struct lysp_notif *notif;
2912
Radek Krejci2c4e7172018-10-19 15:56:26 +02002913 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002914
2915 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002916 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002917 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002918 notif->nodetype = LYS_NOTIF;
2919 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002920
Radek Krejci6d6556c2018-11-08 09:37:45 +01002921 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002922 switch (kw) {
2923 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002924 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 +02002925 break;
2926 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002927 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 +02002928 break;
2929 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002930 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 +02002931 break;
2932 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002933 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002934 break;
2935
2936 case YANG_ANYDATA:
2937 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002938 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002939 break;
2940 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002941 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002942 break;
2943 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002944 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002945 break;
2946 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002947 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002948 break;
2949 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002950 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002951 break;
2952 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002953 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002954 break;
2955 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002956 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002957 break;
2958
2959 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002960 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002961 break;
2962 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002963 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002964 break;
2965 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002966 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002967 break;
2968 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002969 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002970 break;
2971 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002972 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002973 return LY_EVALID;
2974 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002975 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002976 return ret;
2977}
2978
Michal Vaskoea5abea2018-09-18 13:10:54 +02002979/**
2980 * @brief Parse the grouping statement.
2981 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002982 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002983 * @param[in,out] data Data to read from, always moved to currently handled character.
2984 * @param[in,out] groupings Groupings to add to.
2985 *
2986 * @return LY_ERR values.
2987 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002988static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002989parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002990{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002991 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002992 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002993 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002994 enum yang_keyword kw;
2995 struct lysp_grp *grp;
2996
Radek Krejci2c4e7172018-10-19 15:56:26 +02002997 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002998
2999 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003000 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003001 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003002 grp->nodetype = LYS_GROUPING;
3003 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003004
Radek Krejci6d6556c2018-11-08 09:37:45 +01003005 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003006 switch (kw) {
3007 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003008 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 +02003009 break;
3010 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003011 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 +02003012 break;
3013 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003014 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003015 break;
3016
3017 case YANG_ANYDATA:
3018 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003019 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003020 break;
3021 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003022 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003023 break;
3024 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003025 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003026 break;
3027 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003028 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003029 break;
3030 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003031 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032 break;
3033 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003034 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003035 break;
3036 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003037 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003038 break;
3039
3040 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003041 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003042 break;
3043 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003044 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003045 break;
3046 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003047 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003048 break;
3049 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003050 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003051 break;
3052 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003053 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003054 break;
3055 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003056 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003057 return LY_EVALID;
3058 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003059 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003060 return ret;
3061}
3062
Michal Vaskoea5abea2018-09-18 13:10:54 +02003063/**
3064 * @brief Parse the refine statement.
3065 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003066 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003067 * @param[in,out] data Data to read from, always moved to currently handled character.
3068 * @param[in,out] augments Augments to add to.
3069 *
3070 * @return LY_ERR values.
3071 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003072static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003073parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003074{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003075 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003077 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003078 enum yang_keyword kw;
3079 struct lysp_augment *aug;
3080
Radek Krejci2c4e7172018-10-19 15:56:26 +02003081 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003082
3083 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003084 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003085 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003086 aug->nodetype = LYS_AUGMENT;
3087 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003088
Radek Krejci6d6556c2018-11-08 09:37:45 +01003089 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003090 switch (kw) {
3091 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003092 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 +02003093 break;
3094 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003095 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 +02003096 break;
3097 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003098 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 +02003099 break;
3100 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003101 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003102 break;
3103 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003104 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003105 break;
3106
3107 case YANG_ANYDATA:
3108 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003109 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003110 break;
3111 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003112 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003113 break;
3114 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003115 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003116 break;
3117 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003118 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003119 break;
3120 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003121 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003122 break;
3123 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003124 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003125 break;
3126 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003127 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003128 break;
3129 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003130 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003131 break;
3132
3133 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003134 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135 break;
3136 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003137 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003138 break;
3139 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003140 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003141 break;
3142 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003143 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003144 return LY_EVALID;
3145 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003146 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003147 return ret;
3148}
3149
Michal Vaskoea5abea2018-09-18 13:10:54 +02003150/**
3151 * @brief Parse the uses statement.
3152 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003153 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003154 * @param[in,out] data Data to read from, always moved to currently handled character.
3155 * @param[in,out] siblings Siblings to add to.
3156 *
3157 * @return LY_ERR values.
3158 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003159static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003160parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003161{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003162 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003163 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003164 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003165 enum yang_keyword kw;
3166 struct lysp_node *iter;
3167 struct lysp_node_uses *uses;
3168
3169 /* create structure */
3170 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003171 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003172 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003173 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003174
3175 /* insert into siblings */
3176 if (!*siblings) {
3177 *siblings = (struct lysp_node *)uses;
3178 } else {
3179 for (iter = *siblings; iter->next; iter = iter->next);
3180 iter->next = (struct lysp_node *)uses;
3181 }
3182
3183 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003184 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003185 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003186
3187 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003188 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003189 switch (kw) {
3190 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003191 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 +02003192 break;
3193 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003194 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 +02003195 break;
3196 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003197 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 +02003198 break;
3199 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003200 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003201 break;
3202 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003203 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003204 break;
3205
3206 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003207 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003208 break;
3209 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003210 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003211 break;
3212 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003213 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003214 break;
3215 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003216 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003217 return LY_EVALID;
3218 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003219 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003220 return ret;
3221}
3222
Michal Vaskoea5abea2018-09-18 13:10:54 +02003223/**
3224 * @brief Parse the case statement.
3225 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003226 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003227 * @param[in,out] data Data to read from, always moved to currently handled character.
3228 * @param[in,out] siblings Siblings to add to.
3229 *
3230 * @return LY_ERR values.
3231 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003232static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003233parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003234{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003235 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003236 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003237 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003238 enum yang_keyword kw;
3239 struct lysp_node *iter;
3240 struct lysp_node_case *cas;
3241
3242 /* create structure */
3243 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003244 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003245 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003246 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003247
3248 /* insert into siblings */
3249 if (!*siblings) {
3250 *siblings = (struct lysp_node *)cas;
3251 } else {
3252 for (iter = *siblings; iter->next; iter = iter->next);
3253 iter->next = (struct lysp_node *)cas;
3254 }
3255
3256 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003257 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003258 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003259
3260 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003261 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003262 switch (kw) {
3263 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003264 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 +02003265 break;
3266 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003267 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 +02003268 break;
3269 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003270 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 +02003271 break;
3272 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003273 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003274 break;
3275 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003276 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003277 break;
3278
3279 case YANG_ANYDATA:
3280 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003281 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003282 break;
3283 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003284 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003285 break;
3286 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003287 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003288 break;
3289 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003290 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003291 break;
3292 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003293 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003294 break;
3295 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003296 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297 break;
3298 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003299 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003300 break;
3301 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003302 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003303 break;
3304 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003305 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003306 return LY_EVALID;
3307 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003308 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003309 return ret;
3310}
3311
Michal Vaskoea5abea2018-09-18 13:10:54 +02003312/**
3313 * @brief Parse the choice statement.
3314 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003315 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003316 * @param[in,out] data Data to read from, always moved to currently handled character.
3317 * @param[in,out] siblings Siblings to add to.
3318 *
3319 * @return LY_ERR values.
3320 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003321static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003322parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003323{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003324 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003325 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003326 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003327 enum yang_keyword kw;
3328 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003329 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003330
3331 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003332 choice = calloc(1, sizeof *choice);
3333 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3334 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003335 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003336
3337 /* insert into siblings */
3338 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003339 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003340 } else {
3341 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003342 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003343 }
3344
3345 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003346 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003347 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003348
3349 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003350 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003351 switch (kw) {
3352 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003353 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003354 break;
3355 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003356 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 +02003357 break;
3358 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003359 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 +02003360 break;
3361 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003362 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003363 break;
3364 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003365 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 +02003366 break;
3367 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003368 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003369 break;
3370 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003371 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003372 break;
3373 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003374 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_IDENTIF_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003375 break;
3376
3377 case YANG_ANYDATA:
3378 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003379 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003380 break;
3381 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003382 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003383 break;
3384 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003385 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003386 break;
3387 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003388 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003389 break;
3390 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003391 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003392 break;
3393 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003394 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003395 break;
3396 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003397 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003398 break;
3399 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003400 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003401 break;
3402 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003403 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003404 return LY_EVALID;
3405 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003406 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003407 return ret;
3408}
3409
Michal Vaskoea5abea2018-09-18 13:10:54 +02003410/**
3411 * @brief Parse the container statement.
3412 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003413 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003414 * @param[in,out] data Data to read from, always moved to currently handled character.
3415 * @param[in,out] siblings Siblings to add to.
3416 *
3417 * @return LY_ERR values.
3418 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003419static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003420parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003421{
3422 LY_ERR ret = 0;
3423 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003424 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003425 enum yang_keyword kw;
3426 struct lysp_node *iter;
3427 struct lysp_node_container *cont;
3428
3429 /* create structure */
3430 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003431 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003432 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003433 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003434
3435 /* insert into siblings */
3436 if (!*siblings) {
3437 *siblings = (struct lysp_node *)cont;
3438 } else {
3439 for (iter = *siblings; iter->next; iter = iter->next);
3440 iter->next = (struct lysp_node *)cont;
3441 }
3442
3443 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003444 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003445 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003446
3447 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003448 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003449 switch (kw) {
3450 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003451 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003452 break;
3453 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003454 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 +02003455 break;
3456 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003457 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 +02003458 break;
3459 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003460 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 +02003461 break;
3462 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003463 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003464 break;
3465 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003466 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003467 break;
3468 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003469 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 +02003470 break;
3471
3472 case YANG_ANYDATA:
3473 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003474 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003475 break;
3476 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003477 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003478 break;
3479 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003480 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003481 break;
3482 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003483 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003484 break;
3485 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003486 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003487 break;
3488 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003489 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003490 break;
3491 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003492 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003493 break;
3494
3495 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003496 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003497 break;
3498 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003499 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003500 break;
3501 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003502 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003503 break;
3504 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003505 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003506 break;
3507 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003508 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003509 break;
3510 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003511 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003512 break;
3513 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003514 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003515 return LY_EVALID;
3516 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003517 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003518 return ret;
3519}
3520
Michal Vaskoea5abea2018-09-18 13:10:54 +02003521/**
3522 * @brief Parse the list statement.
3523 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003524 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003525 * @param[in,out] data Data to read from, always moved to currently handled character.
3526 * @param[in,out] siblings Siblings to add to.
3527 *
3528 * @return LY_ERR values.
3529 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003531parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003532{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003533 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003534 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003535 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003536 enum yang_keyword kw;
3537 struct lysp_node *iter;
3538 struct lysp_node_list *list;
3539
3540 /* create structure */
3541 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003542 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003544 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003545
3546 /* insert into siblings */
3547 if (!*siblings) {
3548 *siblings = (struct lysp_node *)list;
3549 } else {
3550 for (iter = *siblings; iter->next; iter = iter->next);
3551 iter->next = (struct lysp_node *)list;
3552 }
3553
3554 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003555 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003556 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003557
3558 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003559 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003560 switch (kw) {
3561 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003562 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003563 break;
3564 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003565 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 +02003566 break;
3567 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003568 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 +02003569 break;
3570 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003571 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 +02003572 break;
3573 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003574 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003575 break;
3576 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003577 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003578 break;
3579 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003580 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 +02003581 break;
3582 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003583 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584 break;
3585 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003586 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003587 break;
3588 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003589 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590 break;
3591 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003592 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 +02003593 break;
3594
3595 case YANG_ANYDATA:
3596 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003597 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003598 break;
3599 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003600 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003601 break;
3602 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003603 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003604 break;
3605 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003606 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003607 break;
3608 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003609 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610 break;
3611 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003612 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003613 break;
3614 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003615 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003616 break;
3617
3618 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003619 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003620 break;
3621 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003622 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003623 break;
3624 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003625 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003626 break;
3627 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003628 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003629 break;
3630 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003631 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003632 break;
3633 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003634 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003635 break;
3636 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003637 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003638 return LY_EVALID;
3639 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003640 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003641
3642 return ret;
3643}
3644
Michal Vaskoea5abea2018-09-18 13:10:54 +02003645/**
3646 * @brief Parse the yin-element statement.
3647 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003648 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003649 * @param[in,out] data Data to read from, always moved to currently handled character.
3650 * @param[in,out] flags Flags to write to.
3651 * @param[in,out] exts Extension instances to add to.
3652 *
3653 * @return LY_ERR values.
3654 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003655static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003656parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003657{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003658 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003659 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003660 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003661 enum yang_keyword kw;
3662
3663 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003664 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003665 return LY_EVALID;
3666 }
3667
3668 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003669 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003670
3671 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3672 *flags |= LYS_YINELEM_TRUE;
3673 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3674 *flags |= LYS_YINELEM_FALSE;
3675 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003676 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003677 free(buf);
3678 return LY_EVALID;
3679 }
3680 free(buf);
3681
Radek Krejci6d6556c2018-11-08 09:37:45 +01003682 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003683 switch (kw) {
3684 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003685 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3686 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003687 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003688 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003689 return LY_EVALID;
3690 }
3691 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003692 return ret;
3693}
3694
Michal Vaskoea5abea2018-09-18 13:10:54 +02003695/**
3696 * @brief Parse the yin-element statement.
3697 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003698 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003699 * @param[in,out] data Data to read from, always moved to currently handled character.
3700 * @param[in,out] argument Value to write to.
3701 * @param[in,out] flags Flags to write to.
3702 * @param[in,out] exts Extension instances to add to.
3703 *
3704 * @return LY_ERR values.
3705 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003706static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003707parse_argument(struct ly_parser_ctx *ctx, const char **data, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003708{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003709 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003710 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003711 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003712 enum yang_keyword kw;
3713
3714 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003715 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003716 return LY_EVALID;
3717 }
3718
3719 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003720 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003721 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003722
Radek Krejci6d6556c2018-11-08 09:37:45 +01003723 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003724 switch (kw) {
3725 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003726 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003727 break;
3728 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003729 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003730 break;
3731 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003732 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003733 return LY_EVALID;
3734 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003735 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003736 return ret;
3737}
3738
Michal Vaskoea5abea2018-09-18 13:10:54 +02003739/**
3740 * @brief Parse the extension statement.
3741 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003742 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003743 * @param[in,out] data Data to read from, always moved to currently handled character.
3744 * @param[in,out] extensions Extensions to add to.
3745 *
3746 * @return LY_ERR values.
3747 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003748static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003749parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003750{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003751 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003752 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003753 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003754 enum yang_keyword kw;
3755 struct lysp_ext *ex;
3756
Radek Krejci2c4e7172018-10-19 15:56:26 +02003757 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003758
3759 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003760 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003761 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003762
Radek Krejci6d6556c2018-11-08 09:37:45 +01003763 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003764 switch (kw) {
3765 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003766 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 +02003767 break;
3768 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003769 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 +02003770 break;
3771 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003772 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003773 break;
3774 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003775 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003776 break;
3777 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003778 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003779 break;
3780 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003781 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003782 return LY_EVALID;
3783 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003784 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003785 return ret;
3786}
3787
Michal Vaskoea5abea2018-09-18 13:10:54 +02003788/**
3789 * @brief Parse the deviate statement.
3790 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003791 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003792 * @param[in,out] data Data to read from, always moved to currently handled character.
3793 * @param[in,out] deviates Deviates to add to.
3794 *
3795 * @return LY_ERR values.
3796 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003797static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003798parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003799{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003800 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003801 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003802 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003803 enum yang_keyword kw;
3804 struct lysp_deviate *iter, *d;
3805 struct lysp_deviate_add *d_add = NULL;
3806 struct lysp_deviate_rpl *d_rpl = NULL;
3807 struct lysp_deviate_del *d_del = NULL;
3808 const char **d_units, ***d_uniques, ***d_dflts;
3809 struct lysp_restr **d_musts;
3810 uint16_t *d_flags;
3811 uint32_t *d_min, *d_max;
3812
3813 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003814 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003815
3816 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3817 dev_mod = LYS_DEV_NOT_SUPPORTED;
3818 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3819 dev_mod = LYS_DEV_ADD;
3820 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3821 dev_mod = LYS_DEV_REPLACE;
3822 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3823 dev_mod = LYS_DEV_DELETE;
3824 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003825 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003826 free(buf);
3827 return LY_EVALID;
3828 }
3829 free(buf);
3830
3831 /* create structure */
3832 switch (dev_mod) {
3833 case LYS_DEV_NOT_SUPPORTED:
3834 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003835 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003836 break;
3837 case LYS_DEV_ADD:
3838 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003839 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003840 d = (struct lysp_deviate *)d_add;
3841 d_units = &d_add->units;
3842 d_uniques = &d_add->uniques;
3843 d_dflts = &d_add->dflts;
3844 d_musts = &d_add->musts;
3845 d_flags = &d_add->flags;
3846 d_min = &d_add->min;
3847 d_max = &d_add->max;
3848 break;
3849 case LYS_DEV_REPLACE:
3850 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003851 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003852 d = (struct lysp_deviate *)d_rpl;
3853 d_units = &d_rpl->units;
3854 d_flags = &d_rpl->flags;
3855 d_min = &d_rpl->min;
3856 d_max = &d_rpl->max;
3857 break;
3858 case LYS_DEV_DELETE:
3859 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003860 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003861 d = (struct lysp_deviate *)d_del;
3862 d_units = &d_del->units;
3863 d_uniques = &d_del->uniques;
3864 d_dflts = &d_del->dflts;
3865 d_musts = &d_del->musts;
3866 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003867 break;
3868 default:
3869 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003870 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003871 }
3872 d->mod = dev_mod;
3873
3874 /* insert into siblings */
3875 if (!*deviates) {
3876 *deviates = d;
3877 } else {
3878 for (iter = *deviates; iter->next; iter = iter->next);
3879 iter->next = d;
3880 }
3881
Radek Krejci6d6556c2018-11-08 09:37:45 +01003882 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003883 switch (kw) {
3884 case YANG_CONFIG:
3885 switch (dev_mod) {
3886 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003887 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003888 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003889 return LY_EVALID;
3890 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003891 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003892 break;
3893 }
3894 break;
3895 case YANG_DEFAULT:
3896 switch (dev_mod) {
3897 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003898 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003899 return LY_EVALID;
3900 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003901 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 +02003902 break;
3903 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003904 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 +02003905 break;
3906 }
3907 break;
3908 case YANG_MANDATORY:
3909 switch (dev_mod) {
3910 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003911 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003912 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003913 return LY_EVALID;
3914 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003915 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003916 break;
3917 }
3918 break;
3919 case YANG_MAX_ELEMENTS:
3920 switch (dev_mod) {
3921 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003922 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003923 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003924 return LY_EVALID;
3925 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003926 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003927 break;
3928 }
3929 break;
3930 case YANG_MIN_ELEMENTS:
3931 switch (dev_mod) {
3932 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003933 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003934 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003935 return LY_EVALID;
3936 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003937 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003938 break;
3939 }
3940 break;
3941 case YANG_MUST:
3942 switch (dev_mod) {
3943 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003944 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003945 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003946 return LY_EVALID;
3947 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003948 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003949 break;
3950 }
3951 break;
3952 case YANG_TYPE:
3953 switch (dev_mod) {
3954 case LYS_DEV_NOT_SUPPORTED:
3955 case LYS_DEV_ADD:
3956 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003957 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003958 return LY_EVALID;
3959 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003960 if (d_rpl->type) {
3961 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
3962 return LY_EVALID;
3963 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003964 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003965 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003966 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003967 break;
3968 }
3969 break;
3970 case YANG_UNIQUE:
3971 switch (dev_mod) {
3972 case LYS_DEV_NOT_SUPPORTED:
3973 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003974 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003975 return LY_EVALID;
3976 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003977 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 +02003978 break;
3979 }
3980 break;
3981 case YANG_UNITS:
3982 switch (dev_mod) {
3983 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003984 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003985 return LY_EVALID;
3986 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003987 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 +02003988 break;
3989 }
3990 break;
3991 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003992 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003993 break;
3994 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003995 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003996 return LY_EVALID;
3997 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003998 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003999 return ret;
4000}
4001
Michal Vaskoea5abea2018-09-18 13:10:54 +02004002/**
4003 * @brief Parse the deviation statement.
4004 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004005 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004006 * @param[in,out] data Data to read from, always moved to currently handled character.
4007 * @param[in,out] deviations Deviations to add to.
4008 *
4009 * @return LY_ERR values.
4010 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004011static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004012parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004013{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004014 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004015 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004016 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017 enum yang_keyword kw;
4018 struct lysp_deviation *dev;
4019
Radek Krejci2c4e7172018-10-19 15:56:26 +02004020 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004021
4022 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004023 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004024 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004025
Radek Krejci6d6556c2018-11-08 09:37:45 +01004026 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004027 switch (kw) {
4028 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004029 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 +02004030 break;
4031 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004032 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004033 break;
4034 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004035 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 +02004036 break;
4037 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004038 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004039 break;
4040 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004041 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004042 return LY_EVALID;
4043 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004044 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004045 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004046checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004047 /* mandatory substatements */
4048 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004049 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004050 return LY_EVALID;
4051 }
4052
4053 return ret;
4054}
4055
Michal Vaskoea5abea2018-09-18 13:10:54 +02004056/**
4057 * @brief Parse the feature statement.
4058 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004059 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004060 * @param[in,out] data Data to read from, always moved to currently handled character.
4061 * @param[in,out] features Features to add to.
4062 *
4063 * @return LY_ERR values.
4064 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004065static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004066parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004067{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004068 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004069 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004070 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004071 enum yang_keyword kw;
4072 struct lysp_feature *feat;
4073
Radek Krejci2c4e7172018-10-19 15:56:26 +02004074 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004075
4076 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004077 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004078 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004079
4080 CHECK_UNIQUENESS(ctx, *features, name, "feature", feat->name);
4081
Radek Krejci6d6556c2018-11-08 09:37:45 +01004082 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004083 switch (kw) {
4084 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004085 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 +02004086 break;
4087 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004088 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 +02004089 break;
4090 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004091 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 +02004092 break;
4093 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004094 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004095 break;
4096 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004097 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004098 break;
4099 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004100 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004101 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004102 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004103 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004104 return ret;
4105}
4106
Michal Vaskoea5abea2018-09-18 13:10:54 +02004107/**
4108 * @brief Parse the identity statement.
4109 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004110 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004111 * @param[in,out] data Data to read from, always moved to currently handled character.
4112 * @param[in,out] identities Identities to add to.
4113 *
4114 * @return LY_ERR values.
4115 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004116static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004117parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004118{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004119 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004120 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004121 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004122 enum yang_keyword kw;
4123 struct lysp_ident *ident;
4124
Radek Krejci2c4e7172018-10-19 15:56:26 +02004125 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004126
4127 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004128 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004129 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004130
4131 CHECK_UNIQUENESS(ctx, *identities, name, "identity", ident->name);
4132
Radek Krejci6d6556c2018-11-08 09:37:45 +01004133 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004134 switch (kw) {
4135 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004136 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 +02004137 break;
4138 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004139 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 +02004140 break;
4141 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004142 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 +02004143 break;
4144 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004145 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004146 break;
4147 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004148 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 +02004149 break;
4150 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004151 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004152 break;
4153 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004154 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004155 return LY_EVALID;
4156 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004157 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004158 return ret;
4159}
4160
Michal Vaskoea5abea2018-09-18 13:10:54 +02004161/**
4162 * @brief Parse the module or submodule statement.
4163 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004164 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004165 * @param[in,out] data Data to read from, always moved to currently handled character.
4166 * @param[in,out] mod Module to write to.
4167 *
4168 * @return LY_ERR values.
4169 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004170static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004171parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004172{
4173 LY_ERR ret = 0;
4174 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004175 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004176 enum yang_keyword kw, prev_kw = 0;
4177 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejcie9e987e2018-10-31 12:50:27 +01004178 struct lysp_module *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179
4180 /* (sub)module name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004181 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004182 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004183
Radek Krejci6d6556c2018-11-08 09:37:45 +01004184 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004185
Radek Krejcie3846472018-10-15 15:24:51 +02004186#define CHECK_ORDER(SECTION) \
4187 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4188
Michal Vasko7fbc8162018-09-17 10:35:16 +02004189 switch (kw) {
4190 /* module header */
4191 case YANG_NAMESPACE:
4192 case YANG_PREFIX:
4193 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004194 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004195 return LY_EVALID;
4196 }
Radek Krejcie3846472018-10-15 15:24:51 +02004197 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4198 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004199 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004200 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004201 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004202 return LY_EVALID;
4203 }
Radek Krejcie3846472018-10-15 15:24:51 +02004204 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4205 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004206 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004207 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004208 break;
4209 /* linkage */
4210 case YANG_INCLUDE:
4211 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004212 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004213 break;
4214 /* meta */
4215 case YANG_ORGANIZATION:
4216 case YANG_CONTACT:
4217 case YANG_DESCRIPTION:
4218 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004219 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004220 break;
4221
4222 /* revision */
4223 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004224 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004225 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004226 /* body */
4227 case YANG_ANYDATA:
4228 case YANG_ANYXML:
4229 case YANG_AUGMENT:
4230 case YANG_CHOICE:
4231 case YANG_CONTAINER:
4232 case YANG_DEVIATION:
4233 case YANG_EXTENSION:
4234 case YANG_FEATURE:
4235 case YANG_GROUPING:
4236 case YANG_IDENTITY:
4237 case YANG_LEAF:
4238 case YANG_LEAF_LIST:
4239 case YANG_LIST:
4240 case YANG_NOTIFICATION:
4241 case YANG_RPC:
4242 case YANG_TYPEDEF:
4243 case YANG_USES:
4244 case YANG_CUSTOM:
4245 mod_stmt = Y_MOD_BODY;
4246 break;
4247 default:
4248 /* error handled in the next switch */
4249 break;
4250 }
Radek Krejcie3846472018-10-15 15:24:51 +02004251#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004252
Radek Krejcie3846472018-10-15 15:24:51 +02004253 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004254 switch (kw) {
4255 /* module header */
4256 case YANG_YANG_VERSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004257 LY_CHECK_RET(parse_yangversion(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004258 break;
4259 case YANG_NAMESPACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004260 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->ns, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004261 break;
4262 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004263 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts));
Radek Krejci70853c52018-10-15 14:46:16 +02004264 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004265 break;
4266 case YANG_BELONGS_TO:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004267 LY_CHECK_RET(parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004268 break;
4269
4270 /* linkage */
4271 case YANG_INCLUDE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004272 LY_CHECK_RET(parse_include(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004273 break;
4274 case YANG_IMPORT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004275 LY_CHECK_RET(parse_import(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004276 break;
4277
4278 /* meta */
4279 case YANG_ORGANIZATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004280 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->org, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004281 break;
4282 case YANG_CONTACT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004283 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->contact, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004284 break;
4285 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004286 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->dsc, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004287 break;
4288 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004289 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->ref, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004290 break;
4291
4292 /* revision */
4293 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004294 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004295 break;
4296
4297 /* body */
4298 case YANG_ANYDATA:
4299 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004300 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004301 break;
4302 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004303 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004304 break;
4305 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004306 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004307 break;
4308 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004309 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004310 break;
4311 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004312 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004313 break;
4314 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004315 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004316 break;
4317 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004318 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004319 break;
4320
4321 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004322 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004323 break;
4324 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004325 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004326 break;
4327 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004328 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004329 break;
4330 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004331 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004332 break;
4333 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004334 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004335 break;
4336 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004337 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004338 break;
4339 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004340 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004341 break;
4342 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004343 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004344 break;
4345 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004346 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004347 break;
4348 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004349 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004350 break;
4351
4352 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004353 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004354 return LY_EVALID;
4355 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004356 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004357 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004358checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004359 /* mandatory substatements */
4360 if (mod->submodule) {
4361 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004362 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004363 return LY_EVALID;
4364 }
4365 } else {
4366 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004367 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004368 return LY_EVALID;
4369 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004370 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004371 return LY_EVALID;
4372 }
4373 }
4374
Radek Krejcie9e987e2018-10-31 12:50:27 +01004375 /* submodules share the namespace with the module names, so there must not be
4376 * a submodule of the same name in the context, no need for revision matching */
4377 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL);
4378 if (dup && (!mod->submodule || strcmp(dup->belongsto, mod->belongsto))) {
4379 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
4380 mod->submodule ? "submodules" : "module and submodule", mod->name);
4381 return LY_EVALID;
4382 }
4383
Michal Vasko7fbc8162018-09-17 10:35:16 +02004384 return ret;
4385}
4386
Radek Krejcid4557c62018-09-17 11:42:09 +02004387LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01004388yang_parse(struct ly_parser_ctx *context, const char *data, struct lysp_module **mod_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004389{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004390 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004391 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004392 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004393 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004394 struct lysp_module *mod = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004395
4396 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004397 ret = get_keyword(context, &data, &kw, &word, &word_len);
4398 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004399
4400 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004401 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004402 ly_stmt2str(kw));
Radek Krejcibbe09a92018-11-08 09:36:54 +01004403 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004404 }
4405
4406 mod = calloc(1, sizeof *mod);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004407 LY_CHECK_ERR_GOTO(!mod, LOGMEM(context->ctx), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004408 if (kw == YANG_SUBMODULE) {
4409 mod->submodule = 1;
4410 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01004411 mod->parsing = 1;
4412 mod->ctx = context->ctx;
4413 context->mod = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004414
4415 /* substatements */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004416 ret = parse_sub_module(context, &data, mod);
4417 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004418
4419 /* read some trailing spaces or new lines */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004420 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4421 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422
4423 if (word) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004424 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004425 word_len, word);
4426 free(buf);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004427 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004428 }
4429 assert(!buf);
4430
Radek Krejcibbe09a92018-11-08 09:36:54 +01004431 mod->parsing = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004432 *mod_p = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004433
Radek Krejcibbe09a92018-11-08 09:36:54 +01004434cleanup:
4435 if (ret) {
4436 lysp_module_free(mod);
4437 }
4438
Michal Vasko7fbc8162018-09-17 10:35:16 +02004439 return ret;
4440}