blob: e9878f83d7c367b1abdb113d68dcd365b816a6d4 [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));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002184 break;
2185 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002186 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002187 break;
2188 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002189 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002190 break;
2191 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002192 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002193 break;
2194 case YANG_LENGTH:
2195 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002196 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002197 return LY_EVALID;
2198 }
2199 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002200 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002201
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002202 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002203 break;
2204 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002205 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002206 break;
2207 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002208 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002209 break;
2210 case YANG_RANGE:
2211 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002212 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002213 return LY_EVALID;
2214 }
2215 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002216 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002217
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002218 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002219 break;
2220 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002221 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002222 break;
2223 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002224 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2225 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002226 break;
2227 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002228 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002229 break;
2230 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002231 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002232 return LY_EVALID;
2233 }
Radek Krejci4f28eda2018-11-12 11:46:16 +01002234
2235 if (kw != YANG_CUSTOM) {
2236 type->flags |= LYS_TYPE_MODIFIED;
2237 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002238 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002239 return ret;
2240}
2241
Michal Vaskoea5abea2018-09-18 13:10:54 +02002242/**
2243 * @brief Parse the leaf statement.
2244 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002245 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002246 * @param[in,out] data Data to read from, always moved to currently handled character.
2247 * @param[in,out] siblings Siblings to add to.
2248 *
2249 * @return LY_ERR values.
2250 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002251static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002252parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002253{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002254 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002255 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002256 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002257 enum yang_keyword kw;
2258 struct lysp_node *iter;
2259 struct lysp_node_leaf *leaf;
2260
2261 /* create structure */
2262 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002263 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002264 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002265 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002266
2267 /* insert into siblings */
2268 if (!*siblings) {
2269 *siblings = (struct lysp_node *)leaf;
2270 } else {
2271 for (iter = *siblings; iter->next; iter = iter->next);
2272 iter->next = (struct lysp_node *)leaf;
2273 }
2274
2275 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002276 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002277 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002278
2279 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002280 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002281 switch (kw) {
2282 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002283 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002284 break;
2285 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002286 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 +02002287 break;
2288 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002289 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 +02002290 break;
2291 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002292 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 +02002293 break;
2294 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002295 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002296 break;
2297 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002298 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002299 break;
2300 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002301 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 +02002302 break;
2303 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002304 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002305 break;
2306 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002307 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002308 break;
2309 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002310 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 +02002311 break;
2312 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002313 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002314 break;
2315 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002316 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002317 break;
2318 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002319 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002320 return LY_EVALID;
2321 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002322 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002323 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002324checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002325 /* mandatory substatements */
2326 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002327 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002328 return LY_EVALID;
2329 }
2330
2331 return ret;
2332}
2333
Michal Vaskoea5abea2018-09-18 13:10:54 +02002334/**
2335 * @brief Parse the max-elements statement.
2336 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002337 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002338 * @param[in,out] data Data to read from, always moved to currently handled character.
2339 * @param[in,out] max Value to write to.
2340 * @param[in,out] flags Flags to write to.
2341 * @param[in,out] exts Extension instances to add to.
2342 *
2343 * @return LY_ERR values.
2344 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002345static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002346parse_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 +02002347{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002348 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002349 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002350 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002351 unsigned long int num;
2352 enum yang_keyword kw;
2353
2354 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002355 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002356 return LY_EVALID;
2357 }
2358 *flags |= LYS_SET_MAX;
2359
2360 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002361 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002362
2363 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002364 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002365 free(buf);
2366 return LY_EVALID;
2367 }
2368
2369 if (strncmp(word, "unbounded", word_len)) {
2370 errno = 0;
2371 num = strtoul(word, &ptr, 10);
2372 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002373 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002374 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002375 free(buf);
2376 return LY_EVALID;
2377 }
2378 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002379 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002380 free(buf);
2381 return LY_EVALID;
2382 }
2383
2384 *max = num;
2385 }
2386 free(buf);
2387
Radek Krejci6d6556c2018-11-08 09:37:45 +01002388 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002389 switch (kw) {
2390 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002391 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002392 break;
2393 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002394 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002395 return LY_EVALID;
2396 }
2397 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002398 return ret;
2399}
2400
Michal Vaskoea5abea2018-09-18 13:10:54 +02002401/**
2402 * @brief Parse the min-elements statement.
2403 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002404 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002405 * @param[in,out] data Data to read from, always moved to currently handled character.
2406 * @param[in,out] min Value to write to.
2407 * @param[in,out] flags Flags to write to.
2408 * @param[in,out] exts Extension instances to add to.
2409 *
2410 * @return LY_ERR values.
2411 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002412static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002413parse_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 +02002414{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002415 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002416 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002417 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002418 unsigned long int num;
2419 enum yang_keyword kw;
2420
2421 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002422 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002423 return LY_EVALID;
2424 }
2425 *flags |= LYS_SET_MIN;
2426
2427 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002428 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002429
2430 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002431 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002432 free(buf);
2433 return LY_EVALID;
2434 }
2435
2436 errno = 0;
2437 num = strtoul(word, &ptr, 10);
2438 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002439 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002440 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002441 free(buf);
2442 return LY_EVALID;
2443 }
2444 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002445 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002446 free(buf);
2447 return LY_EVALID;
2448 }
2449 *min = num;
2450 free(buf);
2451
Radek Krejci6d6556c2018-11-08 09:37:45 +01002452 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002453 switch (kw) {
2454 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002455 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002456 break;
2457 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002458 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002459 return LY_EVALID;
2460 }
2461 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002462 return ret;
2463}
2464
Michal Vaskoea5abea2018-09-18 13:10:54 +02002465/**
2466 * @brief Parse the ordered-by statement.
2467 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002468 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002469 * @param[in,out] data Data to read from, always moved to currently handled character.
2470 * @param[in,out] flags Flags to write to.
2471 * @param[in,out] exts Extension instances to add to.
2472 *
2473 * @return LY_ERR values.
2474 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002475static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002476parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002477{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002478 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002479 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002480 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002481 enum yang_keyword kw;
2482
2483 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002484 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002485 return LY_EVALID;
2486 }
2487
2488 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002489 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002490
2491 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2492 *flags |= LYS_ORDBY_SYSTEM;
2493 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2494 *flags |= LYS_ORDBY_USER;
2495 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002496 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002497 free(buf);
2498 return LY_EVALID;
2499 }
2500 free(buf);
2501
Radek Krejci6d6556c2018-11-08 09:37:45 +01002502 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002503 switch (kw) {
2504 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002505 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002506 break;
2507 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002508 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002509 return LY_EVALID;
2510 }
2511 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002512 return ret;
2513}
2514
Michal Vaskoea5abea2018-09-18 13:10:54 +02002515/**
2516 * @brief Parse the leaf-list statement.
2517 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002518 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002519 * @param[in,out] data Data to read from, always moved to currently handled character.
2520 * @param[in,out] siblings Siblings to add to.
2521 *
2522 * @return LY_ERR values.
2523 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002524static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002525parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002526{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002527 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002528 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002529 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002530 enum yang_keyword kw;
2531 struct lysp_node *iter;
2532 struct lysp_node_leaflist *llist;
2533
2534 /* create structure */
2535 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002536 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002537 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002538 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002539
2540 /* insert into siblings */
2541 if (!*siblings) {
2542 *siblings = (struct lysp_node *)llist;
2543 } else {
2544 for (iter = *siblings; iter->next; iter = iter->next);
2545 iter->next = (struct lysp_node *)llist;
2546 }
2547
2548 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002549 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002550 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002551
2552 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002553 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002554 switch (kw) {
2555 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002556 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002557 break;
2558 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002559 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 +02002560 break;
2561 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002562 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002563 break;
2564 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002565 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 +02002566 break;
2567 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002568 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002569 break;
2570 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002571 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002572 break;
2573 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002574 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002575 break;
2576 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002577 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002578 break;
2579 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002580 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 +02002581 break;
2582 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002583 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002584 break;
2585 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002586 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002587 break;
2588 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002589 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 +02002590 break;
2591 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002592 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002593 break;
2594 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002595 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002596 break;
2597 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002598 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002599 return LY_EVALID;
2600 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002601 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002602 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002603checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002604 /* mandatory substatements */
2605 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002606 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002607 return LY_EVALID;
2608 }
2609
2610 return ret;
2611}
2612
Michal Vaskoea5abea2018-09-18 13:10:54 +02002613/**
2614 * @brief Parse the refine statement.
2615 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002616 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002617 * @param[in,out] data Data to read from, always moved to currently handled character.
2618 * @param[in,out] refines Refines to add to.
2619 *
2620 * @return LY_ERR values.
2621 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002622static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002623parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002624{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002625 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002626 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002627 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002628 enum yang_keyword kw;
2629 struct lysp_refine *rf;
2630
Radek Krejci2c4e7172018-10-19 15:56:26 +02002631 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002632
2633 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002634 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002635 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002636
Radek Krejci6d6556c2018-11-08 09:37:45 +01002637 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002638 switch (kw) {
2639 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002640 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002641 break;
2642 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002643 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 +02002644 break;
2645 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002646 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 +02002647 break;
2648 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002649 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 +02002650 break;
2651 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002652 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002653 break;
2654 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002655 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002656 break;
2657 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002658 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002659 break;
2660 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002661 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002662 break;
2663 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002664 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 +02002665 break;
2666 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002667 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 +02002668 break;
2669 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002670 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002671 break;
2672 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002673 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002674 return LY_EVALID;
2675 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002676 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002677 return ret;
2678}
2679
Michal Vaskoea5abea2018-09-18 13:10:54 +02002680/**
2681 * @brief Parse the typedef statement.
2682 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002683 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002684 * @param[in,out] data Data to read from, always moved to currently handled character.
2685 * @param[in,out] typedefs Typedefs to add to.
2686 *
2687 * @return LY_ERR values.
2688 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002689static LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01002690parse_typedef(struct ly_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002691{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002692 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002693 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002694 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002695 enum yang_keyword kw;
2696 struct lysp_tpdf *tpdf;
2697
Radek Krejci2c4e7172018-10-19 15:56:26 +02002698 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002699
2700 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002701 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002702 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002703
2704 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002705 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002706 switch (kw) {
2707 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002708 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 +02002709 break;
2710 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002711 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 +02002712 break;
2713 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002714 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 +02002715 break;
2716 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002717 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002718 break;
2719 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002720 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002721 break;
2722 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002723 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 +02002724 break;
2725 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002726 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002727 break;
2728 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002729 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002730 return LY_EVALID;
2731 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002732 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002733 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002734checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002735 /* mandatory substatements */
2736 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002737 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002738 return LY_EVALID;
2739 }
2740
Radek Krejcibbe09a92018-11-08 09:36:54 +01002741 /* store data for collision check */
2742 if (parent) {
2743 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2744 }
2745
Michal Vasko7fbc8162018-09-17 10:35:16 +02002746 return ret;
2747}
2748
Michal Vaskoea5abea2018-09-18 13:10:54 +02002749/**
2750 * @brief Parse the input or output statement.
2751 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002752 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002753 * @param[in,out] data Data to read from, always moved to currently handled character.
2754 * @param[in] kw Type of this particular keyword
2755 * @param[in,out] inout_p Input/output pointer to write to.
2756 *
2757 * @return LY_ERR values.
2758 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002759static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002760parse_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 +02002761{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002762 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002763 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002764 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002765 struct lysp_action_inout *inout;
2766
2767 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002768 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002769 return LY_EVALID;
2770 }
2771
2772 /* create structure */
2773 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002774 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002775 *inout_p = inout;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002776 inout->nodetype = LYS_INOUT;
2777 inout->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002778
2779 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002780 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002781 switch (kw) {
2782 case YANG_ANYDATA:
2783 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002784 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002785 break;
2786 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002787 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002788 break;
2789 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002790 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002791 break;
2792 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002793 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002794 break;
2795 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002796 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002797 break;
2798 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002799 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002800 break;
2801 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002802 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002803 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002804 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002805 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout, data, &inout->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002806 break;
2807 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002808 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002809 break;
2810 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002811 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout, &inout->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002812 break;
2813 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002814 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002815 break;
2816 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002817 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002818 return LY_EVALID;
2819 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002820 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002821 return ret;
2822}
2823
Michal Vaskoea5abea2018-09-18 13:10:54 +02002824/**
2825 * @brief Parse the action statement.
2826 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002827 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002828 * @param[in,out] data Data to read from, always moved to currently handled character.
2829 * @param[in,out] actions Actions to add to.
2830 *
2831 * @return LY_ERR values.
2832 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002833static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002834parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002835{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002836 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002837 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002838 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002839 enum yang_keyword kw;
2840 struct lysp_action *act;
2841
Radek Krejci2c4e7172018-10-19 15:56:26 +02002842 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002843
2844 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002845 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002846 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002847 act->nodetype = LYS_ACTION;
2848 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002849
Radek Krejci6d6556c2018-11-08 09:37:45 +01002850 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002851 switch (kw) {
2852 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002853 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 +02002854 break;
2855 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002856 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 +02002857 break;
2858 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002859 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 +02002860 break;
2861 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002862 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863 break;
2864
2865 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002866 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002867 break;
2868 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002869 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002870 break;
2871
2872 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002873 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002874 break;
2875 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002876 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002877 break;
2878 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002879 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002880 break;
2881 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002882 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002883 return LY_EVALID;
2884 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002885 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002886 return ret;
2887}
2888
Michal Vaskoea5abea2018-09-18 13:10:54 +02002889/**
2890 * @brief Parse the notification statement.
2891 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002892 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002893 * @param[in,out] data Data to read from, always moved to currently handled character.
2894 * @param[in,out] notifs Notifications to add to.
2895 *
2896 * @return LY_ERR values.
2897 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002898static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002899parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002900{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002901 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002902 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002903 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002904 enum yang_keyword kw;
2905 struct lysp_notif *notif;
2906
Radek Krejci2c4e7172018-10-19 15:56:26 +02002907 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002908
2909 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002910 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002911 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002912 notif->nodetype = LYS_NOTIF;
2913 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002914
Radek Krejci6d6556c2018-11-08 09:37:45 +01002915 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002916 switch (kw) {
2917 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002918 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 +02002919 break;
2920 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002921 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 +02002922 break;
2923 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002924 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 +02002925 break;
2926 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002927 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002928 break;
2929
2930 case YANG_ANYDATA:
2931 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002932 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002933 break;
2934 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002935 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002936 break;
2937 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002938 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002939 break;
2940 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002941 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002942 break;
2943 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002944 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002945 break;
2946 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002947 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002948 break;
2949 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002950 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002951 break;
2952
2953 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002954 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002955 break;
2956 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002957 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002958 break;
2959 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002960 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002961 break;
2962 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002963 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002964 break;
2965 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002966 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002967 return LY_EVALID;
2968 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002969 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002970 return ret;
2971}
2972
Michal Vaskoea5abea2018-09-18 13:10:54 +02002973/**
2974 * @brief Parse the grouping statement.
2975 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002976 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002977 * @param[in,out] data Data to read from, always moved to currently handled character.
2978 * @param[in,out] groupings Groupings to add to.
2979 *
2980 * @return LY_ERR values.
2981 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002982static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002983parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002984{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002985 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002986 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002987 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002988 enum yang_keyword kw;
2989 struct lysp_grp *grp;
2990
Radek Krejci2c4e7172018-10-19 15:56:26 +02002991 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002992
2993 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002994 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002995 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002996 grp->nodetype = LYS_GROUPING;
2997 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002998
Radek Krejci6d6556c2018-11-08 09:37:45 +01002999 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003000 switch (kw) {
3001 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003002 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 +02003003 break;
3004 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003005 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 +02003006 break;
3007 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003008 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003009 break;
3010
3011 case YANG_ANYDATA:
3012 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003013 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003014 break;
3015 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003016 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003017 break;
3018 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003019 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003020 break;
3021 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003022 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003023 break;
3024 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003025 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003026 break;
3027 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003028 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003029 break;
3030 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003031 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032 break;
3033
3034 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003035 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003036 break;
3037 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003038 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003039 break;
3040 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003041 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003042 break;
3043 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003044 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003045 break;
3046 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003047 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003048 break;
3049 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003050 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003051 return LY_EVALID;
3052 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003053 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003054 return ret;
3055}
3056
Michal Vaskoea5abea2018-09-18 13:10:54 +02003057/**
3058 * @brief Parse the refine statement.
3059 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003060 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003061 * @param[in,out] data Data to read from, always moved to currently handled character.
3062 * @param[in,out] augments Augments to add to.
3063 *
3064 * @return LY_ERR values.
3065 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003066static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003067parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003068{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003069 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003070 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003071 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003072 enum yang_keyword kw;
3073 struct lysp_augment *aug;
3074
Radek Krejci2c4e7172018-10-19 15:56:26 +02003075 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076
3077 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003078 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003079 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003080 aug->nodetype = LYS_AUGMENT;
3081 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003082
Radek Krejci6d6556c2018-11-08 09:37:45 +01003083 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003084 switch (kw) {
3085 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003086 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 +02003087 break;
3088 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003089 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 +02003090 break;
3091 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003092 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 +02003093 break;
3094 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003095 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003096 break;
3097 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003098 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003099 break;
3100
3101 case YANG_ANYDATA:
3102 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003103 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003104 break;
3105 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003106 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003107 break;
3108 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003109 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003110 break;
3111 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003112 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003113 break;
3114 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003115 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003116 break;
3117 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003118 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003119 break;
3120 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003121 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003122 break;
3123 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003124 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003125 break;
3126
3127 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003128 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003129 break;
3130 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003131 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003132 break;
3133 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003134 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135 break;
3136 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003137 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003138 return LY_EVALID;
3139 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003140 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003141 return ret;
3142}
3143
Michal Vaskoea5abea2018-09-18 13:10:54 +02003144/**
3145 * @brief Parse the uses statement.
3146 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003147 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003148 * @param[in,out] data Data to read from, always moved to currently handled character.
3149 * @param[in,out] siblings Siblings to add to.
3150 *
3151 * @return LY_ERR values.
3152 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003153static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003154parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003155{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003156 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003157 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003158 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003159 enum yang_keyword kw;
3160 struct lysp_node *iter;
3161 struct lysp_node_uses *uses;
3162
3163 /* create structure */
3164 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003165 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003166 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003167 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003168
3169 /* insert into siblings */
3170 if (!*siblings) {
3171 *siblings = (struct lysp_node *)uses;
3172 } else {
3173 for (iter = *siblings; iter->next; iter = iter->next);
3174 iter->next = (struct lysp_node *)uses;
3175 }
3176
3177 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003178 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003179 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003180
3181 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003182 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003183 switch (kw) {
3184 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003185 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 +02003186 break;
3187 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003188 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 +02003189 break;
3190 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003191 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 +02003192 break;
3193 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003194 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003195 break;
3196 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003197 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003198 break;
3199
3200 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003201 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003202 break;
3203 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003204 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003205 break;
3206 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003207 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003208 break;
3209 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003210 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003211 return LY_EVALID;
3212 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003213 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003214 return ret;
3215}
3216
Michal Vaskoea5abea2018-09-18 13:10:54 +02003217/**
3218 * @brief Parse the case statement.
3219 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003220 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003221 * @param[in,out] data Data to read from, always moved to currently handled character.
3222 * @param[in,out] siblings Siblings to add to.
3223 *
3224 * @return LY_ERR values.
3225 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003226static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003227parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003228{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003229 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003230 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003231 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003232 enum yang_keyword kw;
3233 struct lysp_node *iter;
3234 struct lysp_node_case *cas;
3235
3236 /* create structure */
3237 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003238 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003239 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003240 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003241
3242 /* insert into siblings */
3243 if (!*siblings) {
3244 *siblings = (struct lysp_node *)cas;
3245 } else {
3246 for (iter = *siblings; iter->next; iter = iter->next);
3247 iter->next = (struct lysp_node *)cas;
3248 }
3249
3250 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003251 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003252 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003253
3254 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003255 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003256 switch (kw) {
3257 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003258 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 +02003259 break;
3260 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003261 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 +02003262 break;
3263 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003264 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 +02003265 break;
3266 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003267 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003268 break;
3269 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003270 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003271 break;
3272
3273 case YANG_ANYDATA:
3274 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003275 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003276 break;
3277 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003278 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003279 break;
3280 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003281 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003282 break;
3283 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003284 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003285 break;
3286 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003287 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003288 break;
3289 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003290 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003291 break;
3292 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003293 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003294 break;
3295 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003296 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297 break;
3298 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003299 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003300 return LY_EVALID;
3301 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003302 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003303 return ret;
3304}
3305
Michal Vaskoea5abea2018-09-18 13:10:54 +02003306/**
3307 * @brief Parse the choice statement.
3308 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003309 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003310 * @param[in,out] data Data to read from, always moved to currently handled character.
3311 * @param[in,out] siblings Siblings to add to.
3312 *
3313 * @return LY_ERR values.
3314 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003315static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003316parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003317{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003318 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003319 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003320 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003321 enum yang_keyword kw;
3322 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003323 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003324
3325 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003326 choice = calloc(1, sizeof *choice);
3327 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3328 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003329 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003330
3331 /* insert into siblings */
3332 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003333 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003334 } else {
3335 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003336 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003337 }
3338
3339 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003340 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003341 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003342
3343 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003344 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003345 switch (kw) {
3346 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003347 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003348 break;
3349 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003350 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 +02003351 break;
3352 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003353 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 +02003354 break;
3355 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003356 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003357 break;
3358 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003359 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 +02003360 break;
3361 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003362 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003363 break;
3364 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003365 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003366 break;
3367 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003368 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 +02003369 break;
3370
3371 case YANG_ANYDATA:
3372 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003373 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003374 break;
3375 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003376 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003377 break;
3378 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003379 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003380 break;
3381 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003382 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003383 break;
3384 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003385 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003386 break;
3387 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003388 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003389 break;
3390 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003391 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003392 break;
3393 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003394 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003395 break;
3396 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003397 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003398 return LY_EVALID;
3399 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003400 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003401 return ret;
3402}
3403
Michal Vaskoea5abea2018-09-18 13:10:54 +02003404/**
3405 * @brief Parse the container statement.
3406 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003407 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003408 * @param[in,out] data Data to read from, always moved to currently handled character.
3409 * @param[in,out] siblings Siblings to add to.
3410 *
3411 * @return LY_ERR values.
3412 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003413static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003414parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003415{
3416 LY_ERR ret = 0;
3417 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003418 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003419 enum yang_keyword kw;
3420 struct lysp_node *iter;
3421 struct lysp_node_container *cont;
3422
3423 /* create structure */
3424 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003425 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003426 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003427 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003428
3429 /* insert into siblings */
3430 if (!*siblings) {
3431 *siblings = (struct lysp_node *)cont;
3432 } else {
3433 for (iter = *siblings; iter->next; iter = iter->next);
3434 iter->next = (struct lysp_node *)cont;
3435 }
3436
3437 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003438 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003439 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003440
3441 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003442 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003443 switch (kw) {
3444 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003445 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003446 break;
3447 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003448 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 +02003449 break;
3450 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003451 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 +02003452 break;
3453 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003454 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 +02003455 break;
3456 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003457 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003458 break;
3459 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003460 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003461 break;
3462 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003463 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 +02003464 break;
3465
3466 case YANG_ANYDATA:
3467 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003468 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003469 break;
3470 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003471 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003472 break;
3473 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003474 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003475 break;
3476 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003477 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003478 break;
3479 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003480 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003481 break;
3482 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003483 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003484 break;
3485 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003486 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003487 break;
3488
3489 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003490 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003491 break;
3492 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003493 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003494 break;
3495 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003496 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003497 break;
3498 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003499 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003500 break;
3501 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003502 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003503 break;
3504 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003505 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003506 break;
3507 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003508 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003509 return LY_EVALID;
3510 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003511 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003512 return ret;
3513}
3514
Michal Vaskoea5abea2018-09-18 13:10:54 +02003515/**
3516 * @brief Parse the list statement.
3517 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003518 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003519 * @param[in,out] data Data to read from, always moved to currently handled character.
3520 * @param[in,out] siblings Siblings to add to.
3521 *
3522 * @return LY_ERR values.
3523 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003524static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003525parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003526{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003527 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003528 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003529 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530 enum yang_keyword kw;
3531 struct lysp_node *iter;
3532 struct lysp_node_list *list;
3533
3534 /* create structure */
3535 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003536 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003537 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003538 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003539
3540 /* insert into siblings */
3541 if (!*siblings) {
3542 *siblings = (struct lysp_node *)list;
3543 } else {
3544 for (iter = *siblings; iter->next; iter = iter->next);
3545 iter->next = (struct lysp_node *)list;
3546 }
3547
3548 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003549 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003550 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003551
3552 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003553 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003554 switch (kw) {
3555 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003556 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003557 break;
3558 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003559 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 +02003560 break;
3561 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003562 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 +02003563 break;
3564 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003565 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 +02003566 break;
3567 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003568 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569 break;
3570 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003571 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003572 break;
3573 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003574 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 +02003575 break;
3576 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003577 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003578 break;
3579 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003580 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003581 break;
3582 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003583 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584 break;
3585 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003586 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 +02003587 break;
3588
3589 case YANG_ANYDATA:
3590 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003591 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003592 break;
3593 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003594 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003595 break;
3596 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003597 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003598 break;
3599 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003600 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003601 break;
3602 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003603 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003604 break;
3605 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003606 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003607 break;
3608 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003609 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610 break;
3611
3612 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003613 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003614 break;
3615 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003616 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003617 break;
3618 case YANG_ACTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003619 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003620 break;
3621 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003622 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003623 break;
3624 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003625 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003626 break;
3627 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003628 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003629 break;
3630 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003631 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003632 return LY_EVALID;
3633 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003634 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003635
3636 return ret;
3637}
3638
Michal Vaskoea5abea2018-09-18 13:10:54 +02003639/**
3640 * @brief Parse the yin-element statement.
3641 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003642 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003643 * @param[in,out] data Data to read from, always moved to currently handled character.
3644 * @param[in,out] flags Flags to write to.
3645 * @param[in,out] exts Extension instances to add to.
3646 *
3647 * @return LY_ERR values.
3648 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003649static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003650parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003651{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003652 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003653 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003654 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003655 enum yang_keyword kw;
3656
3657 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003658 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003659 return LY_EVALID;
3660 }
3661
3662 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003663 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003664
3665 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3666 *flags |= LYS_YINELEM_TRUE;
3667 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3668 *flags |= LYS_YINELEM_FALSE;
3669 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003670 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003671 free(buf);
3672 return LY_EVALID;
3673 }
3674 free(buf);
3675
Radek Krejci6d6556c2018-11-08 09:37:45 +01003676 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003677 switch (kw) {
3678 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003679 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3680 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003681 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003682 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003683 return LY_EVALID;
3684 }
3685 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003686 return ret;
3687}
3688
Michal Vaskoea5abea2018-09-18 13:10:54 +02003689/**
3690 * @brief Parse the yin-element statement.
3691 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003692 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003693 * @param[in,out] data Data to read from, always moved to currently handled character.
3694 * @param[in,out] argument Value to write to.
3695 * @param[in,out] flags Flags to write to.
3696 * @param[in,out] exts Extension instances to add to.
3697 *
3698 * @return LY_ERR values.
3699 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003700static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003701parse_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 +02003702{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003703 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003704 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003705 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003706 enum yang_keyword kw;
3707
3708 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003709 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003710 return LY_EVALID;
3711 }
3712
3713 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003714 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003715 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003716
Radek Krejci6d6556c2018-11-08 09:37:45 +01003717 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003718 switch (kw) {
3719 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003720 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003721 break;
3722 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003723 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003724 break;
3725 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003726 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003727 return LY_EVALID;
3728 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003729 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003730 return ret;
3731}
3732
Michal Vaskoea5abea2018-09-18 13:10:54 +02003733/**
3734 * @brief Parse the extension statement.
3735 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003736 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003737 * @param[in,out] data Data to read from, always moved to currently handled character.
3738 * @param[in,out] extensions Extensions to add to.
3739 *
3740 * @return LY_ERR values.
3741 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003742static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003743parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003744{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003745 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003746 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003747 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003748 enum yang_keyword kw;
3749 struct lysp_ext *ex;
3750
Radek Krejci2c4e7172018-10-19 15:56:26 +02003751 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003752
3753 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003754 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003755 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003756
Radek Krejci6d6556c2018-11-08 09:37:45 +01003757 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003758 switch (kw) {
3759 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003760 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 +02003761 break;
3762 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003763 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 +02003764 break;
3765 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003766 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003767 break;
3768 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003769 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003770 break;
3771 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003772 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003773 break;
3774 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003775 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003776 return LY_EVALID;
3777 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003778 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003779 return ret;
3780}
3781
Michal Vaskoea5abea2018-09-18 13:10:54 +02003782/**
3783 * @brief Parse the deviate statement.
3784 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003785 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003786 * @param[in,out] data Data to read from, always moved to currently handled character.
3787 * @param[in,out] deviates Deviates to add to.
3788 *
3789 * @return LY_ERR values.
3790 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003791static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003792parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003793{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003794 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003795 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003796 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003797 enum yang_keyword kw;
3798 struct lysp_deviate *iter, *d;
3799 struct lysp_deviate_add *d_add = NULL;
3800 struct lysp_deviate_rpl *d_rpl = NULL;
3801 struct lysp_deviate_del *d_del = NULL;
3802 const char **d_units, ***d_uniques, ***d_dflts;
3803 struct lysp_restr **d_musts;
3804 uint16_t *d_flags;
3805 uint32_t *d_min, *d_max;
3806
3807 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003808 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003809
3810 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3811 dev_mod = LYS_DEV_NOT_SUPPORTED;
3812 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3813 dev_mod = LYS_DEV_ADD;
3814 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3815 dev_mod = LYS_DEV_REPLACE;
3816 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3817 dev_mod = LYS_DEV_DELETE;
3818 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003819 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003820 free(buf);
3821 return LY_EVALID;
3822 }
3823 free(buf);
3824
3825 /* create structure */
3826 switch (dev_mod) {
3827 case LYS_DEV_NOT_SUPPORTED:
3828 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003829 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003830 break;
3831 case LYS_DEV_ADD:
3832 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003833 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003834 d = (struct lysp_deviate *)d_add;
3835 d_units = &d_add->units;
3836 d_uniques = &d_add->uniques;
3837 d_dflts = &d_add->dflts;
3838 d_musts = &d_add->musts;
3839 d_flags = &d_add->flags;
3840 d_min = &d_add->min;
3841 d_max = &d_add->max;
3842 break;
3843 case LYS_DEV_REPLACE:
3844 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003845 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003846 d = (struct lysp_deviate *)d_rpl;
3847 d_units = &d_rpl->units;
3848 d_flags = &d_rpl->flags;
3849 d_min = &d_rpl->min;
3850 d_max = &d_rpl->max;
3851 break;
3852 case LYS_DEV_DELETE:
3853 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003854 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003855 d = (struct lysp_deviate *)d_del;
3856 d_units = &d_del->units;
3857 d_uniques = &d_del->uniques;
3858 d_dflts = &d_del->dflts;
3859 d_musts = &d_del->musts;
3860 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003861 break;
3862 default:
3863 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003864 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003865 }
3866 d->mod = dev_mod;
3867
3868 /* insert into siblings */
3869 if (!*deviates) {
3870 *deviates = d;
3871 } else {
3872 for (iter = *deviates; iter->next; iter = iter->next);
3873 iter->next = d;
3874 }
3875
Radek Krejci6d6556c2018-11-08 09:37:45 +01003876 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003877 switch (kw) {
3878 case YANG_CONFIG:
3879 switch (dev_mod) {
3880 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003881 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003882 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003883 return LY_EVALID;
3884 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003885 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003886 break;
3887 }
3888 break;
3889 case YANG_DEFAULT:
3890 switch (dev_mod) {
3891 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003892 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003893 return LY_EVALID;
3894 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003895 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 +02003896 break;
3897 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003898 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 +02003899 break;
3900 }
3901 break;
3902 case YANG_MANDATORY:
3903 switch (dev_mod) {
3904 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003905 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003906 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003907 return LY_EVALID;
3908 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003909 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003910 break;
3911 }
3912 break;
3913 case YANG_MAX_ELEMENTS:
3914 switch (dev_mod) {
3915 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003916 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003917 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003918 return LY_EVALID;
3919 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003920 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003921 break;
3922 }
3923 break;
3924 case YANG_MIN_ELEMENTS:
3925 switch (dev_mod) {
3926 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003927 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003928 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003929 return LY_EVALID;
3930 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003931 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003932 break;
3933 }
3934 break;
3935 case YANG_MUST:
3936 switch (dev_mod) {
3937 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003938 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003939 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003940 return LY_EVALID;
3941 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003942 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003943 break;
3944 }
3945 break;
3946 case YANG_TYPE:
3947 switch (dev_mod) {
3948 case LYS_DEV_NOT_SUPPORTED:
3949 case LYS_DEV_ADD:
3950 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003951 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003952 return LY_EVALID;
3953 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02003954 if (d_rpl->type) {
3955 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
3956 return LY_EVALID;
3957 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003958 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003959 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003960 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003961 break;
3962 }
3963 break;
3964 case YANG_UNIQUE:
3965 switch (dev_mod) {
3966 case LYS_DEV_NOT_SUPPORTED:
3967 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003968 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003969 return LY_EVALID;
3970 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003971 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 +02003972 break;
3973 }
3974 break;
3975 case YANG_UNITS:
3976 switch (dev_mod) {
3977 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003978 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003979 return LY_EVALID;
3980 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003981 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 +02003982 break;
3983 }
3984 break;
3985 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003986 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003987 break;
3988 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003989 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003990 return LY_EVALID;
3991 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003992 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003993 return ret;
3994}
3995
Michal Vaskoea5abea2018-09-18 13:10:54 +02003996/**
3997 * @brief Parse the deviation statement.
3998 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003999 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004000 * @param[in,out] data Data to read from, always moved to currently handled character.
4001 * @param[in,out] deviations Deviations to add to.
4002 *
4003 * @return LY_ERR values.
4004 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004005static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004006parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004007{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004008 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004009 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004010 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004011 enum yang_keyword kw;
4012 struct lysp_deviation *dev;
4013
Radek Krejci2c4e7172018-10-19 15:56:26 +02004014 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004015
4016 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004017 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004018 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004019
Radek Krejci6d6556c2018-11-08 09:37:45 +01004020 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004021 switch (kw) {
4022 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004023 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 +02004024 break;
4025 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004026 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004027 break;
4028 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004029 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 +02004030 break;
4031 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004032 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004033 break;
4034 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004035 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004036 return LY_EVALID;
4037 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004038 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004039 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004040checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004041 /* mandatory substatements */
4042 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004043 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004044 return LY_EVALID;
4045 }
4046
4047 return ret;
4048}
4049
Michal Vaskoea5abea2018-09-18 13:10:54 +02004050/**
4051 * @brief Parse the feature statement.
4052 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004053 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004054 * @param[in,out] data Data to read from, always moved to currently handled character.
4055 * @param[in,out] features Features to add to.
4056 *
4057 * @return LY_ERR values.
4058 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004059static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004060parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004061{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004062 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004063 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004064 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004065 enum yang_keyword kw;
4066 struct lysp_feature *feat;
4067
Radek Krejci2c4e7172018-10-19 15:56:26 +02004068 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004069
4070 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004071 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004072 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004073
4074 CHECK_UNIQUENESS(ctx, *features, name, "feature", feat->name);
4075
Radek Krejci6d6556c2018-11-08 09:37:45 +01004076 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004077 switch (kw) {
4078 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004079 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 +02004080 break;
4081 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004082 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 +02004083 break;
4084 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004085 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 +02004086 break;
4087 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004088 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004089 break;
4090 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004091 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004092 break;
4093 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004094 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004095 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004096 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004097 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004098 return ret;
4099}
4100
Michal Vaskoea5abea2018-09-18 13:10:54 +02004101/**
4102 * @brief Parse the identity statement.
4103 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004104 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004105 * @param[in,out] data Data to read from, always moved to currently handled character.
4106 * @param[in,out] identities Identities to add to.
4107 *
4108 * @return LY_ERR values.
4109 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004110static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004111parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004112{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004113 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004114 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004115 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004116 enum yang_keyword kw;
4117 struct lysp_ident *ident;
4118
Radek Krejci2c4e7172018-10-19 15:56:26 +02004119 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004120
4121 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004122 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004123 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004124
4125 CHECK_UNIQUENESS(ctx, *identities, name, "identity", ident->name);
4126
Radek Krejci6d6556c2018-11-08 09:37:45 +01004127 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004128 switch (kw) {
4129 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004130 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 +02004131 break;
4132 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004133 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 +02004134 break;
4135 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004136 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 +02004137 break;
4138 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004139 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004140 break;
4141 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004142 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 +02004143 break;
4144 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004145 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004146 break;
4147 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004148 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004149 return LY_EVALID;
4150 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004151 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004152 return ret;
4153}
4154
Michal Vaskoea5abea2018-09-18 13:10:54 +02004155/**
4156 * @brief Parse the module or submodule statement.
4157 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004158 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004159 * @param[in,out] data Data to read from, always moved to currently handled character.
4160 * @param[in,out] mod Module to write to.
4161 *
4162 * @return LY_ERR values.
4163 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004164static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004165parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004166{
4167 LY_ERR ret = 0;
4168 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004169 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004170 enum yang_keyword kw, prev_kw = 0;
4171 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejcie9e987e2018-10-31 12:50:27 +01004172 struct lysp_module *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004173
4174 /* (sub)module name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004175 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004176 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004177
Radek Krejci6d6556c2018-11-08 09:37:45 +01004178 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179
Radek Krejcie3846472018-10-15 15:24:51 +02004180#define CHECK_ORDER(SECTION) \
4181 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4182
Michal Vasko7fbc8162018-09-17 10:35:16 +02004183 switch (kw) {
4184 /* module header */
4185 case YANG_NAMESPACE:
4186 case YANG_PREFIX:
4187 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004188 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004189 return LY_EVALID;
4190 }
Radek Krejcie3846472018-10-15 15:24:51 +02004191 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4192 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004193 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004194 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004195 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004196 return LY_EVALID;
4197 }
Radek Krejcie3846472018-10-15 15:24:51 +02004198 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4199 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004200 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004201 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004202 break;
4203 /* linkage */
4204 case YANG_INCLUDE:
4205 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004206 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004207 break;
4208 /* meta */
4209 case YANG_ORGANIZATION:
4210 case YANG_CONTACT:
4211 case YANG_DESCRIPTION:
4212 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004213 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004214 break;
4215
4216 /* revision */
4217 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004218 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004219 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004220 /* body */
4221 case YANG_ANYDATA:
4222 case YANG_ANYXML:
4223 case YANG_AUGMENT:
4224 case YANG_CHOICE:
4225 case YANG_CONTAINER:
4226 case YANG_DEVIATION:
4227 case YANG_EXTENSION:
4228 case YANG_FEATURE:
4229 case YANG_GROUPING:
4230 case YANG_IDENTITY:
4231 case YANG_LEAF:
4232 case YANG_LEAF_LIST:
4233 case YANG_LIST:
4234 case YANG_NOTIFICATION:
4235 case YANG_RPC:
4236 case YANG_TYPEDEF:
4237 case YANG_USES:
4238 case YANG_CUSTOM:
4239 mod_stmt = Y_MOD_BODY;
4240 break;
4241 default:
4242 /* error handled in the next switch */
4243 break;
4244 }
Radek Krejcie3846472018-10-15 15:24:51 +02004245#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004246
Radek Krejcie3846472018-10-15 15:24:51 +02004247 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004248 switch (kw) {
4249 /* module header */
4250 case YANG_YANG_VERSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004251 LY_CHECK_RET(parse_yangversion(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004252 break;
4253 case YANG_NAMESPACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004254 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 +02004255 break;
4256 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004257 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 +02004258 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004259 break;
4260 case YANG_BELONGS_TO:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004261 LY_CHECK_RET(parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004262 break;
4263
4264 /* linkage */
4265 case YANG_INCLUDE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004266 LY_CHECK_RET(parse_include(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004267 break;
4268 case YANG_IMPORT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004269 LY_CHECK_RET(parse_import(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004270 break;
4271
4272 /* meta */
4273 case YANG_ORGANIZATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004274 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 +02004275 break;
4276 case YANG_CONTACT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004277 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 +02004278 break;
4279 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004280 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 +02004281 break;
4282 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004283 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 +02004284 break;
4285
4286 /* revision */
4287 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004288 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004289 break;
4290
4291 /* body */
4292 case YANG_ANYDATA:
4293 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004294 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004295 break;
4296 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004297 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004298 break;
4299 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004300 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004301 break;
4302 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004303 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004304 break;
4305 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004306 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004307 break;
4308 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004309 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004310 break;
4311 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004312 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004313 break;
4314
4315 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004316 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004317 break;
4318 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004319 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004320 break;
4321 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004322 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004323 break;
4324 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004325 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004326 break;
4327 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004328 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004329 break;
4330 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004331 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004332 break;
4333 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004334 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004335 break;
4336 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004337 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004338 break;
4339 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004340 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004341 break;
4342 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004343 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004344 break;
4345
4346 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004347 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004348 return LY_EVALID;
4349 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004350 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004351 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004352checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004353 /* mandatory substatements */
4354 if (mod->submodule) {
4355 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004356 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004357 return LY_EVALID;
4358 }
4359 } else {
4360 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004361 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004362 return LY_EVALID;
4363 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004364 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004365 return LY_EVALID;
4366 }
4367 }
4368
Radek Krejcie9e987e2018-10-31 12:50:27 +01004369 /* submodules share the namespace with the module names, so there must not be
4370 * a submodule of the same name in the context, no need for revision matching */
4371 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL);
4372 if (dup && (!mod->submodule || strcmp(dup->belongsto, mod->belongsto))) {
4373 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
4374 mod->submodule ? "submodules" : "module and submodule", mod->name);
4375 return LY_EVALID;
4376 }
4377
Michal Vasko7fbc8162018-09-17 10:35:16 +02004378 return ret;
4379}
4380
Radek Krejcid4557c62018-09-17 11:42:09 +02004381LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01004382yang_parse(struct ly_parser_ctx *context, const char *data, struct lysp_module **mod_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004383{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004384 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004385 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004386 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004387 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004388 struct lysp_module *mod = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004389
4390 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004391 ret = get_keyword(context, &data, &kw, &word, &word_len);
4392 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004393
4394 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004395 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004396 ly_stmt2str(kw));
Radek Krejcibbe09a92018-11-08 09:36:54 +01004397 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004398 }
4399
4400 mod = calloc(1, sizeof *mod);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004401 LY_CHECK_ERR_GOTO(!mod, LOGMEM(context->ctx), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004402 if (kw == YANG_SUBMODULE) {
4403 mod->submodule = 1;
4404 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01004405 mod->parsing = 1;
4406 mod->ctx = context->ctx;
4407 context->mod = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004408
4409 /* substatements */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004410 ret = parse_sub_module(context, &data, mod);
4411 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004412
4413 /* read some trailing spaces or new lines */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004414 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4415 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004416
4417 if (word) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004418 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004419 word_len, word);
4420 free(buf);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004421 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004422 }
4423 assert(!buf);
4424
Radek Krejcibbe09a92018-11-08 09:36:54 +01004425 mod->parsing = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004426 *mod_p = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004427
Radek Krejcibbe09a92018-11-08 09:36:54 +01004428cleanup:
4429 if (ret) {
4430 lysp_module_free(mod);
4431 }
4432
Michal Vasko7fbc8162018-09-17 10:35:16 +02004433 return ret;
4434}