blob: 58647773a1253870970b5b1b766dc50e506ee583 [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"
30
Radek Krejci44ceedc2018-10-02 15:54:31 +020031struct ly_parser_ctx {
32 struct ly_ctx *ctx;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020033 uint64_t line; /* line number */
34 uint64_t indent; /* current position on the line for indentation */
Radek Krejci44ceedc2018-10-02 15:54:31 +020035};
36
37/* Macro to check YANG's yang-char grammar rule */
38#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
39 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
40 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
41 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
42 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
43 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
44 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
45 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
46 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
47 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
48
49/* These 2 macros checks YANG's identifier grammar rule */
50#define is_yangidentstartchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
51#define is_yangidentchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || \
52 c == '_' || c == '-' || c == '.')
53
Radek Krejci9fcacc12018-10-11 15:59:11 +020054#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
55 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
56 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020057
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020058#define MOVE_INPUT(CTX, DATA, COUNT) (*(data))+=COUNT;(CTX)->indent+=COUNT
59
Radek Krejci44ceedc2018-10-02 15:54:31 +020060#define LOGVAL_YANG(CTX, ...) LOGVAL((CTX)->ctx, LY_VLOG_LINE, &(CTX)->line, __VA_ARGS__)
61
Michal Vaskoea5abea2018-09-18 13:10:54 +020062/**
63 * @brief Loop through all substatements providing, return if there are none.
64 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020065 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020066 * @param[in] DATA Raw data to read from.
67 * @param[out] KW YANG keyword read.
68 * @param[out] WORD Pointer to the keyword itself.
69 * @param[out] WORD_LEN Length of the keyword.
70 * @param[out] ERR Variable for error storing.
71 *
72 * @return In case there are no substatements or a fatal error encountered.
73 */
Michal Vasko7fbc8162018-09-17 10:35:16 +020074#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR) \
75 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
Radek Krejcic59bc972018-09-17 16:13:06 +020076 LY_CHECK_RET(ERR); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020077 \
78 if (KW == YANG_SEMICOLON) { \
79 return ERR; \
80 } \
81 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +020082 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020083 return LY_EVALID; \
84 } \
85 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
86 !ERR && (KW != YANG_RIGHT_BRACE); \
87 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
88
Radek Krejci44ceedc2018-10-02 15:54:31 +020089static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
90static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
91static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
92static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
93static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
94static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +020095
Michal Vaskoea5abea2018-09-18 13:10:54 +020096/**
97 * @brief Add another character to dynamic buffer, a low-level function.
98 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020099 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200100 *
Radek Krejci404251e2018-10-09 12:06:44 +0200101 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200102 * @param[in, out] input Input string to process.
103 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200104 * @param[in,out] buf Buffer to use, can be moved by realloc().
105 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200106 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200107 *
108 * @return LY_ERR values.
109 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200110static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200111buf_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 +0200112{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200113 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200114 *buf_len += 16;
115 *buf = ly_realloc(*buf, *buf_len);
116 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
117 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200118 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200119
Radek Krejci44ceedc2018-10-02 15:54:31 +0200120 (*buf_used) += len;
121 (*input) += len;
122
Michal Vasko7fbc8162018-09-17 10:35:16 +0200123 return LY_SUCCESS;
124}
125
Michal Vaskoea5abea2018-09-18 13:10:54 +0200126/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200127 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200128 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200129 * @param[in] ctx yang parser context for logging.
130 * @param[in] c UTF8 code point of a character to check.
131 * @return LY_ERR values.
132 */
133static LY_ERR
134check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
135{
136 if (!is_yangutf8char(c)) {
137 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
138 return LY_EVALID;
139 }
140 return LY_SUCCESS;
141}
142
143/**
144 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
145 *
146 * @param[in] ctx yang parser context for logging.
147 * @param[in] c UTF8 code point of a character to check.
148 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200149 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
150 * 0 - colon not yet found (no prefix)
151 * 1 - \p c is the colon character
152 * 2 - prefix already processed, now processing the identifier
153 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200154 * If the identifier cannot be prefixed, NULL is expected.
155 * @return LY_ERR values.
156 */
157static LY_ERR
158check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
159{
160 if (first || (prefix && (*prefix) == 1)) {
161 if (!is_yangidentstartchar(c)) {
162 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
163 return LY_EVALID;
164 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200165 if (prefix) {
166 if (first) {
167 (*prefix) = 0;
168 } else {
169 (*prefix) = 2;
170 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200171 }
172 } else if (c == ':' && prefix && (*prefix) == 0) {
173 (*prefix) = 1;
174 } else if (!is_yangidentchar(c)) {
175 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
176 return LY_EVALID;
177 }
178
179 return LY_SUCCESS;
180}
181
182/**
183 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
184 *
185 * @param[in] ctx yang parser context for logging.
186 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
187 * when function returns.
188 * @param[in] arg Type of the input string to select method of checking character validity.
189 * @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 +0200190 * 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 +0200191 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
192 * @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 +0200193 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200194 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200195 *
196 * @return LY_ERR values.
197 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200198static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200199buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
200 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200201{
Radek Krejci404251e2018-10-09 12:06:44 +0200202 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200203 unsigned int c;
204 size_t len;
205
206 /* get UTF8 code point (and number of bytes coding the character) */
207 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
208 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
209 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200210 if (c == '\n') {
211 ctx->indent = 0;
212 } else {
213 /* note - even the multibyte character is count as 1 */
214 ++ctx->indent;
215 }
216
Radek Krejci44ceedc2018-10-02 15:54:31 +0200217 /* check character validity */
218 switch (arg) {
219 case Y_IDENTIF_ARG:
220 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
221 break;
222 case Y_PREF_IDENTIF_ARG:
223 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
224 break;
225 case Y_STR_ARG:
226 case Y_MAYBE_STR_ARG:
227 LY_CHECK_RET(check_stringchar(ctx, c));
228 break;
229 }
230
Michal Vasko7fbc8162018-09-17 10:35:16 +0200231 if (word_b && *word_b) {
232 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200233 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200234 return LY_EMEM;
235 }
236
237 /* in case of realloc */
238 *word_p = *word_b;
239 } else if (need_buf) {
240 /* first time we need a buffer, copy everything read up to now */
241 if (*word_len) {
242 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200243 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200244 *buf_len = *word_len;
245 memcpy(*word_b, *word_p, *word_len);
246 }
247
248 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200249 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200250 return LY_EMEM;
251 }
252
253 /* in case of realloc */
254 *word_p = *word_b;
255 } else {
256 /* just remember the first character pointer */
257 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200258 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200259 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200260 /* ... and update the word's length */
261 (*word_len) += len;
262 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200263 }
264
265 return LY_SUCCESS;
266}
267
Michal Vaskoea5abea2018-09-18 13:10:54 +0200268/**
269 * @brief Skip YANG comment in data.
270 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200271 * @param[in] ctx yang parser context for logging.
272 * @param[in,out] data Data to read from, automatically moved after the comment.
273 * @param[in] comment Type of the comment to process:
274 * 1 for a one-line comment,
275 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200276 *
277 * @return LY_ERR values.
278 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200279static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200280skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200281{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200282 /* internal statuses: 0 - comment ended,
283 * 1 - in line comment,
284 * 2 - in block comment,
285 * 3 - in block comment with last read character '*'
286 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200287 while (**data && comment) {
288 switch (comment) {
289 case 1:
290 if (**data == '\n') {
291 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200292 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200293 }
294 break;
295 case 2:
296 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200297 comment = 3;
298 } else if (**data == '\n') {
299 ++ctx->line;
300 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200301 break;
302 case 3:
303 if (**data == '/') {
304 comment = 0;
305 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200306 if (**data == '\n') {
307 ++ctx->line;
308 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200309 comment = 2;
310 }
311 break;
312 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200313 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200314 }
315
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200316 if (**data == '\n') {
317 ctx->indent = 0;
318 } else {
319 ++ctx->indent;
320 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200321 ++(*data);
322 }
323
324 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200325 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200326 return LY_EVALID;
327 }
328
329 return LY_SUCCESS;
330}
331
Michal Vaskoea5abea2018-09-18 13:10:54 +0200332/**
333 * @brief Read a quoted string from data.
334 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200335 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200336 * @param[in,out] data Data to read from, always moved to currently handled character.
337 * @param[in] arg Type of YANG keyword argument expected.
338 * @param[out] word_p Pointer to the read quoted string.
339 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
340 * set to NULL. Otherwise equal to \p word_p.
341 * @param[out] word_len Length of the read quoted string.
342 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
343 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
344 * indenation in the final quoted string.
345 *
346 * @return LY_ERR values.
347 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200348static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200349read_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 +0200350 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200351{
352 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
353 * 4 - string finished, now skipping whitespaces looking for +,
354 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200355 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200356 const char *c;
357
358 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200359 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200360 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200361 } else {
362 assert(**data == '\'');
363 string = 1;
364 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200365 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200366
367 while (**data && string) {
368 switch (string) {
369 case 1:
370 switch (**data) {
371 case '\'':
372 /* string may be finished, but check for + */
373 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200374 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200375 break;
376 default:
377 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200378 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 +0200379 break;
380 }
381 break;
382 case 2:
383 switch (**data) {
384 case '\"':
385 /* string may be finished, but check for + */
386 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200387 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200388 break;
389 case '\\':
390 /* special character following */
391 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200392 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200393 break;
394 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200395 if (current_indent < block_indent) {
396 ++current_indent;
397 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200398 } else {
399 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200400 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 +0200401 }
402 break;
403 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200404 if (current_indent < block_indent) {
405 assert(need_buf);
406 current_indent += 8;
407 ctx->indent += 8;
408 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
409 /* store leftover spaces from the tab */
410 c = " ";
411 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 +0200412 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200413 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200414 } else {
415 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200416 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 +0200417 /* additional characters for indentation - only 1 was count in buf_store_char */
418 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200419 }
420 break;
421 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200422 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200423 /* we will be removing the indents so we need our own buffer */
424 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200425
426 /* remove trailing tabs and spaces */
427 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
428 --(*word_len);
429 }
430
431 /* start indentation */
432 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200433 }
434
435 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200436 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
437
438 /* maintain line number */
439 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200440
441 /* reset context indentation counter for possible string after this one */
442 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200443 break;
444 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200445 /* first non-whitespace character, stop eating indentation */
446 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200447
448 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200449 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 +0200450 break;
451 }
452 break;
453 case 3:
454 /* string encoded characters */
455 switch (**data) {
456 case 'n':
457 c = "\n";
458 break;
459 case 't':
460 c = "\t";
461 break;
462 case '\"':
463 c = *data;
464 break;
465 case '\\':
466 c = *data;
467 break;
468 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200469 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200470 return LY_EVALID;
471 }
472
473 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200474 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 +0200475
476 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200477 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200478 break;
479 case 4:
480 switch (**data) {
481 case '+':
482 /* string continues */
483 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200484 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200485 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200486 case '\n':
487 ++ctx->line;
488 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200489 case ' ':
490 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200491 /* just skip */
492 break;
493 default:
494 /* string is finished */
495 goto string_end;
496 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200497 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200498 break;
499 case 5:
500 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200501 case '\n':
502 ++ctx->line;
503 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200504 case ' ':
505 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200506 /* skip */
507 break;
508 case '\'':
509 string = 1;
510 break;
511 case '\"':
512 string = 2;
513 break;
514 default:
515 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200516 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200517 return LY_EVALID;
518 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200519 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200520 break;
521 default:
522 return LY_EINT;
523 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200524 }
525
526string_end:
527 return LY_SUCCESS;
528}
529
Michal Vaskoea5abea2018-09-18 13:10:54 +0200530/**
531 * @brief Get another YANG string from the raw data.
532 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200533 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200534 * @param[in,out] data Data to read from, always moved to currently handled character.
535 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200536 * @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 +0200537 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
538 * set to NULL. Otherwise equal to \p word_p.
539 * @param[out] word_len Length of the read string.
540 *
541 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200542 */
543static LY_ERR
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200544get_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 +0200545{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200546 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200547 LY_ERR ret;
548
549 /* word buffer - dynamically allocated */
550 *word_b = NULL;
551
552 /* word pointer - just a pointer to data */
553 *word_p = NULL;
554
555 *word_len = 0;
556 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200557 switch (**data) {
558 case '\'':
559 case '\"':
560 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200561 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
562 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
563 "unquoted string character, optsep, semicolon or opening brace");
564 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200565 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200566 ret = read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200567 LY_CHECK_RET(ret);
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 Krejci44ceedc2018-10-02 15:54:31 +0200573 ret = skip_comment(ctx, data, 1);
574 } else if ((*data)[1] == '*') {
575 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200576 MOVE_INPUT(ctx, data, 2);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200577 ret = skip_comment(ctx, data, 2);
578 } else {
579 /* not a comment after all */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200580 ret = buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0);
581 }
582 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200583 break;
584 case ' ':
585 if (*word_len) {
586 /* word is finished */
587 goto str_end;
588 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200589 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200590 break;
591 case '\t':
592 if (*word_len) {
593 /* word is finished */
594 goto str_end;
595 }
596 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200597 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200598
599 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200600 break;
601 case '\n':
602 if (*word_len) {
603 /* word is finished */
604 goto str_end;
605 }
606 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200607 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200608
609 /* track line numbers */
610 ++ctx->line;
611
612 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200613 break;
614 case ';':
615 case '{':
616 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
617 /* word is finished */
618 goto str_end;
619 }
620
Radek Krejci44ceedc2018-10-02 15:54:31 +0200621 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200622 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200623 case '}':
624 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
625 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
626 "unquoted string character, optsep, semicolon or opening brace");
627 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200628 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200629 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 +0200630 break;
631 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200632 }
633
634str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200635 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200636 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200637 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
638 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
639 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200640 *word_p = *word_b;
641 }
642
643 return LY_SUCCESS;
644}
645
Michal Vaskoea5abea2018-09-18 13:10:54 +0200646/**
647 * @brief Get another YANG keyword from the raw data.
648 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200649 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200650 * @param[in,out] data Data to read from, always moved to currently handled character.
651 * @param[out] kw YANG keyword read.
652 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
653 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
654 *
655 * @return LY_ERR values.
656 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200657static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200658get_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 +0200659{
660 LY_ERR ret;
661 int prefix;
662 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200663 unsigned int c;
664 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200665
666 if (word_p) {
667 *word_p = NULL;
668 *word_len = 0;
669 }
670
671 /* first skip "optsep", comments */
672 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200673 switch (**data) {
674 case '/':
675 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200676 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200677 MOVE_INPUT(ctx, data, 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200678 ret = skip_comment(ctx, data, 1);
679 if (ret) {
680 return ret;
681 }
Radek Krejcidcc7b322018-10-11 14:24:02 +0200682 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200683 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200684 MOVE_INPUT(ctx, data, 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200685 ret = skip_comment(ctx, data, 2);
686 if (ret) {
687 return ret;
688 }
689 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200690 /* error - not a comment after all, keyword cannot start with slash */
691 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
692 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200693 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200694 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200695 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200696 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200697 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200698 ctx->indent = 0;
699 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200700 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200701 /* skip whitespaces (optsep) */
702 ++ctx->indent;
703 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200704 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200705 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200706 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200707 break;
708 default:
709 /* either a keyword start or an invalid character */
710 goto keyword_start;
711 }
712
713 ++(*data);
714 }
715
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200716#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
717#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
718#define IF_KW_PREFIX_END }
719
Michal Vasko7fbc8162018-09-17 10:35:16 +0200720keyword_start:
721 word_start = *data;
722 *kw = YANG_NONE;
723
724 /* read the keyword itself */
725 switch (**data) {
726 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200727 MOVE_INPUT(ctx, data, 1);
728 IF_KW("rgument", 7, YANG_ARGUMENT)
729 else IF_KW("ugment", 6, YANG_AUGMENT)
730 else IF_KW("ction", 5, YANG_ACTION)
731 else IF_KW_PREFIX("ny", 2)
732 IF_KW("data", 4, YANG_ANYDATA)
733 else IF_KW("xml", 3, YANG_ANYXML)
734 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200735 break;
736 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200737 MOVE_INPUT(ctx, data, 1);
738 IF_KW("ase", 3, YANG_BASE)
739 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
740 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200741 break;
742 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200743 MOVE_INPUT(ctx, data, 1);
744 IF_KW("ase", 3, YANG_CASE)
745 else IF_KW("hoice", 5, YANG_CHOICE)
746 else IF_KW_PREFIX("on", 2)
747 IF_KW("fig", 3, YANG_CONFIG)
748 else IF_KW_PREFIX("ta", 2)
749 IF_KW("ct", 2, YANG_CONTACT)
750 else IF_KW("iner", 4, YANG_CONTAINER)
751 IF_KW_PREFIX_END
752 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200753 break;
754 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200755 MOVE_INPUT(ctx, data, 1);
756 IF_KW_PREFIX("e", 1)
757 IF_KW("fault", 5, YANG_DEFAULT)
758 else IF_KW("scription", 9, YANG_DESCRIPTION)
759 else IF_KW_PREFIX("viat", 4)
760 IF_KW("e", 1, YANG_DEVIATE)
761 else IF_KW("ion", 3, YANG_DEVIATION)
762 IF_KW_PREFIX_END
763 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200764 break;
765 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200766 MOVE_INPUT(ctx, data, 1);
767 IF_KW("num", 3, YANG_ENUM)
768 else IF_KW_PREFIX("rror-", 5)
769 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
770 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
771 IF_KW_PREFIX_END
772 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200773 break;
774 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200775 MOVE_INPUT(ctx, data, 1);
776 IF_KW("eature", 6, YANG_FEATURE)
777 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200778 break;
779 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200780 MOVE_INPUT(ctx, data, 1);
781 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200782 break;
783 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200784 MOVE_INPUT(ctx, data, 1);
785 IF_KW("dentity", 7, YANG_IDENTITY)
786 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
787 else IF_KW("mport", 5, YANG_IMPORT)
788 else IF_KW_PREFIX("n", 1)
789 IF_KW("clude", 5, YANG_INCLUDE)
790 else IF_KW("put", 3, YANG_INPUT)
791 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200792 break;
793 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200794 MOVE_INPUT(ctx, data, 1);
795 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200796 break;
797 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200798 MOVE_INPUT(ctx, data, 1);
799 IF_KW_PREFIX("e", 1)
800 IF_KW("af-list", 7, YANG_LEAF_LIST)
801 else IF_KW("af", 2, YANG_LEAF)
802 else IF_KW("ngth", 4, YANG_LENGTH)
803 IF_KW_PREFIX_END
804 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200805 break;
806 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200807 MOVE_INPUT(ctx, data, 1);
808 IF_KW_PREFIX("a", 1)
809 IF_KW("ndatory", 7, YANG_MANDATORY)
810 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
811 IF_KW_PREFIX_END
812 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
813 else IF_KW("ust", 3, YANG_MUST)
814 else IF_KW_PREFIX("od", 2)
815 IF_KW("ule", 3, YANG_MODULE)
816 else IF_KW("ifier", 5, YANG_MODIFIER)
817 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200818 break;
819 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200820 MOVE_INPUT(ctx, data, 1);
821 IF_KW("amespace", 8, YANG_NAMESPACE)
822 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200823 break;
824 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200825 MOVE_INPUT(ctx, data, 1);
826 IF_KW_PREFIX("r", 1)
827 IF_KW("dered-by", 8, YANG_ORDERED_BY)
828 else IF_KW("ganization", 10, YANG_ORGANIZATION)
829 IF_KW_PREFIX_END
830 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200831 break;
832 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200833 MOVE_INPUT(ctx, data, 1);
834 IF_KW("ath", 3, YANG_PATH)
835 else IF_KW("attern", 6, YANG_PATTERN)
836 else IF_KW("osition", 7, YANG_POSITION)
837 else IF_KW_PREFIX("re", 2)
838 IF_KW("fix", 3, YANG_PREFIX)
839 else IF_KW("sence", 5, YANG_PRESENCE)
840 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200841 break;
842 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200843 MOVE_INPUT(ctx, data, 1);
844 IF_KW("ange", 4, YANG_RANGE)
845 else IF_KW_PREFIX("e", 1)
846 IF_KW_PREFIX("f", 1)
847 IF_KW("erence", 6, YANG_REFERENCE)
848 else IF_KW("ine", 3, YANG_REFINE)
849 IF_KW_PREFIX_END
850 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
851 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
852 else IF_KW("vision", 6, YANG_REVISION)
853 IF_KW_PREFIX_END
854 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200855 break;
856 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200857 MOVE_INPUT(ctx, data, 1);
858 IF_KW("tatus", 5, YANG_STATUS)
859 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200860 break;
861 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200862 MOVE_INPUT(ctx, data, 1);
863 IF_KW("ypedef", 6, YANG_TYPEDEF)
864 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200865 break;
866 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200867 MOVE_INPUT(ctx, data, 1);
868 IF_KW_PREFIX("ni", 2)
869 IF_KW("que", 3, YANG_UNIQUE)
870 else IF_KW("ts", 2, YANG_UNITS)
871 IF_KW_PREFIX_END
872 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200873 break;
874 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200875 MOVE_INPUT(ctx, data, 1);
876 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200877 break;
878 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200879 MOVE_INPUT(ctx, data, 1);
880 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200881 break;
882 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200883 MOVE_INPUT(ctx, data, 1);
884 IF_KW("ang-version", 11, YANG_YANG_VERSION)
885 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200886 break;
887 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200888 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200889 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200890 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200891 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200892 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200893 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200894 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200895 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200896 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200897 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200898 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200899 default:
900 break;
901 }
902
903 if (*kw != YANG_NONE) {
904 /* make sure we have the whole keyword */
905 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200906 case '\n':
907 ++ctx->line;
908 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200909 case ' ':
910 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200911 /* mandatory "sep" */
912 break;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200913 case '{':
914 /* allowed only for input and output statements which can be without arguments */
915 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
916 break;
917 }
918 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200919 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200920 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200921 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
922 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200923 return LY_EVALID;
924 }
925 } else {
926 /* still can be an extension */
927 prefix = 0;
928 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;
973 LY_ERR ret = 0;
974 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 Krejcifc62d7e2018-10-11 12:56:42 +0200983 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +0200984 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200985
Radek Krejci0ae092d2018-09-20 16:43:19 +0200986 if (word) {
987 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200988 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200989 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200990 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200991 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200992 }
993
994 /* insert into parent statements */
995 if (!*child) {
996 *child = stmt;
997 } else {
998 for (par_child = *child; par_child->next; par_child = par_child->next);
999 par_child->next = stmt;
1000 }
1001
1002 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001003 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001004
1005 ret = parse_ext_substmt(ctx, data, word, word_len, &stmt->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001006 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001007 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001008 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001009
1010 return ret;
1011}
1012
Michal Vaskoea5abea2018-09-18 13:10:54 +02001013/**
1014 * @brief Parse extension instance.
1015 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001016 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001017 * @param[in,out] data Data to read from, always moved to currently handled character.
1018 * @param[in] ext_name Extension instance substatement name (keyword).
1019 * @param[in] ext_name_len Extension instance substatement name length.
1020 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1021 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1022 * @param[in,out] exts Extension instances to add to.
1023 *
1024 * @return LY_ERR values.
1025 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001026static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001027parse_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 +02001028 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1029{
1030 LY_ERR ret = 0;
1031 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001032 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001033 struct lysp_ext_instance *e;
1034 enum yang_keyword kw;
1035
1036 LYSP_ARRAY_NEW_RET(ctx, exts, e, LY_EMEM);
1037
1038 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001039 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001040 e->insubstmt = insubstmt;
1041 e->insubstmt_index = insubstmt_index;
1042
1043 /* get optional argument */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001044 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001045 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001046
Radek Krejci0ae092d2018-09-20 16:43:19 +02001047 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001048 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001049 }
1050
1051 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001052 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001053
1054 ret = parse_ext_substmt(ctx, data, word, word_len, &e->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001055 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001056 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001057 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001058
1059 return ret;
1060}
1061
Michal Vaskoea5abea2018-09-18 13:10:54 +02001062/**
1063 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1064 * description, etc...
1065 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001066 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001067 * @param[in,out] data Data to read from, always moved to currently handled character.
1068 * @param[in] substmt Type of this substatement.
1069 * @param[in] substmt_index Index of this substatement.
1070 * @param[in,out] value Place to store the parsed value.
1071 * @param[in] arg Type of the YANG keyword argument (of the value).
1072 * @param[in,out] exts Extension instances to add to.
1073 *
1074 * @return LY_ERR values.
1075 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001076static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001077parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001078 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1079{
1080 LY_ERR ret = 0;
1081 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001082 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001083 enum yang_keyword kw;
1084
1085 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001086 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001087 return LY_EVALID;
1088 }
1089
1090 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001091 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001092 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001093
1094 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001095 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001096
1097 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001098 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001099
1100 switch (kw) {
1101 case YANG_CUSTOM:
1102 ret = parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001103 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001104 break;
1105 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001106 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001107 return LY_EVALID;
1108 }
1109 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001110 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001111
1112 return ret;
1113}
1114
Michal Vaskoea5abea2018-09-18 13:10:54 +02001115/**
1116 * @brief Parse the yang-version statement.
1117 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001118 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001119 * @param[in,out] data Data to read from, always moved to currently handled character.
1120 * @param[in] mod Module to store the parsed information in.
1121 *
1122 * @return LY_ERR values.
1123 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001124static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001125parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001126{
1127 LY_ERR ret = 0;
1128 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001129 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001130 enum yang_keyword kw;
1131
1132 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001133 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001134 return LY_EVALID;
1135 }
1136
1137 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001138 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001139 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001140
1141 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1142 mod->version = LYS_VERSION_1_0;
1143 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1144 mod->version = LYS_VERSION_1_1;
1145 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001146 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001147 free(buf);
1148 return LY_EVALID;
1149 }
1150 free(buf);
1151
1152 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001153 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001154
1155 switch (kw) {
1156 case YANG_CUSTOM:
1157 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001158 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001159 break;
1160 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001161 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001162 return LY_EVALID;
1163 }
1164 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001165 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001166
1167 return ret;
1168}
1169
Michal Vaskoea5abea2018-09-18 13:10:54 +02001170/**
1171 * @brief Parse the belongs-to statement.
1172 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001173 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001174 * @param[in,out] data Data to read from, always moved to currently handled character.
1175 * @param[in,out] belongsto Place to store the parsed value.
1176 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1177 * @param[in,out] exts Extension instances to add to.
1178 *
1179 * @return LY_ERR values.
1180 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001181static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001182parse_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 +02001183{
1184 LY_ERR ret = 0;
1185 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001186 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001187 enum yang_keyword kw;
1188
1189 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001190 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001191 return LY_EVALID;
1192 }
1193
1194 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001195 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001196 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001197
Radek Krejci44ceedc2018-10-02 15:54:31 +02001198 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001199 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001200 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001201
1202 switch (kw) {
1203 case YANG_PREFIX:
1204 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts);
1205 break;
1206 case YANG_CUSTOM:
1207 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts);
1208 break;
1209 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001210 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001211 return LY_EVALID;
1212 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001213 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001214 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001215 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001216
1217 /* mandatory substatements */
1218 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001219 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001220 return LY_EVALID;
1221 }
1222
1223 return ret;
1224}
1225
Michal Vaskoea5abea2018-09-18 13:10:54 +02001226/**
1227 * @brief Parse the revision-date statement.
1228 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001229 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001230 * @param[in,out] data Data to read from, always moved to currently handled character.
1231 * @param[in,out] rev Array to store the parsed value in.
1232 * @param[in,out] exts Extension instances to add to.
1233 *
1234 * @return LY_ERR values.
1235 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001236static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001237parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001238{
1239 LY_ERR ret = 0;
1240 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001241 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001242 enum yang_keyword kw;
1243
1244 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001245 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001246 return LY_EVALID;
1247 }
1248
1249 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001250 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001251 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001252
1253 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001254 if (lysp_check_date(ctx->ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001255 free(buf);
1256 return LY_EVALID;
1257 }
1258
1259 /* store value and spend buf if allocated */
1260 strncpy(rev, word, word_len);
1261 free(buf);
1262
1263 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001264 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001265
1266 switch (kw) {
1267 case YANG_CUSTOM:
1268 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001269 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001270 break;
1271 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001272 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001273 return LY_EVALID;
1274 }
1275 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001276 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001277
1278 return ret;
1279}
1280
Michal Vaskoea5abea2018-09-18 13:10:54 +02001281/**
1282 * @brief Parse the include statement.
1283 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001284 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001285 * @param[in,out] data Data to read from, always moved to currently handled character.
1286 * @param[in,out] includes Parsed includes to add to.
1287 *
1288 * @return LY_ERR values.
1289 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001290static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001291parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001292{
1293 LY_ERR ret = 0;
1294 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001295 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001296 enum yang_keyword kw;
1297 struct lysp_include *inc;
1298
1299 LYSP_ARRAY_NEW_RET(ctx, includes, inc, LY_EMEM);
1300
1301 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001302 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001303 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001304
Radek Krejci44ceedc2018-10-02 15:54:31 +02001305 INSERT_WORD(ctx, buf, inc->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001306 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001307 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001308
1309 switch (kw) {
1310 case YANG_DESCRIPTION:
1311 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts);
1312 break;
1313 case YANG_REFERENCE:
1314 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts);
1315 break;
1316 case YANG_REVISION_DATE:
1317 ret = parse_revisiondate(ctx, data, inc->rev, &inc->exts);
1318 break;
1319 case YANG_CUSTOM:
1320 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts);
1321 break;
1322 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001323 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001324 return LY_EVALID;
1325 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001326 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001327 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001328 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001329
1330 return ret;
1331}
1332
Michal Vaskoea5abea2018-09-18 13:10:54 +02001333/**
1334 * @brief Parse the import statement.
1335 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001336 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001337 * @param[in,out] data Data to read from, always moved to currently handled character.
1338 * @param[in,out] imports Parsed imports to add to.
1339 *
1340 * @return LY_ERR values.
1341 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001342static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001343parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001344{
1345 LY_ERR ret = 0;
1346 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001347 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001348 enum yang_keyword kw;
1349 struct lysp_import *imp;
1350
1351 LYSP_ARRAY_NEW_RET(ctx, imports, imp, LY_EVALID);
1352
1353 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001354 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001355 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001356
Radek Krejci44ceedc2018-10-02 15:54:31 +02001357 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001358 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001359 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001360
1361 switch (kw) {
1362 case YANG_PREFIX:
1363 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts);
1364 break;
1365 case YANG_DESCRIPTION:
1366 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts);
1367 break;
1368 case YANG_REFERENCE:
1369 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts);
1370 break;
1371 case YANG_REVISION_DATE:
1372 ret = parse_revisiondate(ctx, data, imp->rev, &imp->exts);
1373 break;
1374 case YANG_CUSTOM:
1375 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts);
1376 break;
1377 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001378 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001379 return LY_EVALID;
1380 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001381 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001382 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001383 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001384
1385 /* mandatory substatements */
1386 if (!imp->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001387 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001388 return LY_EVALID;
1389 }
1390
1391 return ret;
1392}
1393
Michal Vaskoea5abea2018-09-18 13:10:54 +02001394/**
1395 * @brief Parse the revision statement.
1396 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001397 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001398 * @param[in,out] data Data to read from, always moved to currently handled character.
1399 * @param[in,out] revs Parsed revisions to add to.
1400 *
1401 * @return LY_ERR values.
1402 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001403static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001404parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001405{
1406 LY_ERR ret = 0;
1407 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001408 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001409 enum yang_keyword kw;
1410 struct lysp_revision *rev;
1411
1412 LYSP_ARRAY_NEW_RET(ctx, revs, rev, LY_EMEM);
1413
1414 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001415 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001416 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001417
1418 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001419 if (lysp_check_date(ctx->ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001420 return LY_EVALID;
1421 }
1422
1423 strncpy(rev->rev, word, word_len);
1424 free(buf);
1425
1426 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001427 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001428
1429 switch (kw) {
1430 case YANG_DESCRIPTION:
1431 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts);
1432 break;
1433 case YANG_REFERENCE:
1434 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts);
1435 break;
1436 case YANG_CUSTOM:
1437 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts);
1438 break;
1439 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001440 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001441 return LY_EVALID;
1442 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001443 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001444 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001445 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001446
1447 return ret;
1448}
1449
Michal Vaskoea5abea2018-09-18 13:10:54 +02001450/**
1451 * @brief Parse a generic text field that can have more instances such as base.
1452 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001453 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001454 * @param[in,out] data Data to read from, always moved to currently handled character.
1455 * @param[in] substmt Type of this substatement.
1456 * @param[in,out] texts Parsed values to add to.
1457 * @param[in] arg Type of the expected argument.
1458 * @param[in,out] exts Extension instances to add to.
1459 *
1460 * @return LY_ERR values.
1461 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001462static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001463parse_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 +02001464 struct lysp_ext_instance **exts)
1465{
1466 LY_ERR ret = 0;
1467 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001468 size_t count, word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001469 enum yang_keyword kw;
1470
1471 /* allocate new pointer */
1472 for (count = 1; (*texts) && (*texts)[count - 1]; ++count);
1473 *texts = realloc(*texts, count * sizeof **texts);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001474 LY_CHECK_ERR_RET(!*texts, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001475
1476 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001477 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001478 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001479
Radek Krejci44ceedc2018-10-02 15:54:31 +02001480 INSERT_WORD(ctx, buf, (*texts)[count - 1], word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001481 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001482 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001483
1484 switch (kw) {
1485 case YANG_CUSTOM:
1486 ret = parse_ext(ctx, data, word, word_len, substmt, count - 1, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001487 LY_CHECK_RET(ret);
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), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001491 return LY_EVALID;
1492 }
1493 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001494 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001495
1496 return ret;
1497}
1498
Michal Vaskoea5abea2018-09-18 13:10:54 +02001499/**
1500 * @brief Parse the config statement.
1501 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001502 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001503 * @param[in,out] data Data to read from, always moved to currently handled character.
1504 * @param[in,out] flags Flags to add to.
1505 * @param[in,out] exts Extension instances to add to.
1506 *
1507 * @return LY_ERR values.
1508 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001509static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001510parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001511{
1512 LY_ERR ret = 0;
1513 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001514 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001515 enum yang_keyword kw;
1516
1517 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001518 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001519 return LY_EVALID;
1520 }
1521
1522 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001523 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001524 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001525
1526 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1527 *flags |= LYS_CONFIG_W;
1528 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1529 *flags |= LYS_CONFIG_R;
1530 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001531 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001532 free(buf);
1533 return LY_EVALID;
1534 }
1535 free(buf);
1536
1537 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001538 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001539
1540 switch (kw) {
1541 case YANG_CUSTOM:
1542 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001543 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001544 break;
1545 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001546 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001547 return LY_EVALID;
1548 }
1549 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001550 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001551
1552 return ret;
1553}
1554
Michal Vaskoea5abea2018-09-18 13:10:54 +02001555/**
1556 * @brief Parse the mandatory statement.
1557 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001558 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001559 * @param[in,out] data Data to read from, always moved to currently handled character.
1560 * @param[in,out] flags Flags to add to.
1561 * @param[in,out] exts Extension instances to add to.
1562 *
1563 * @return LY_ERR values.
1564 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001565static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001566parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001567{
1568 LY_ERR ret = 0;
1569 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001570 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001571 enum yang_keyword kw;
1572
1573 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001574 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001575 return LY_EVALID;
1576 }
1577
1578 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001579 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001580 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001581
1582 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1583 *flags |= LYS_MAND_TRUE;
1584 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1585 *flags |= LYS_MAND_FALSE;
1586 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001587 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001588 free(buf);
1589 return LY_EVALID;
1590 }
1591 free(buf);
1592
1593 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001594 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001595
1596 switch (kw) {
1597 case YANG_CUSTOM:
1598 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001599 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001600 break;
1601 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001602 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001603 return LY_EVALID;
1604 }
1605 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001606 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001607
1608 return ret;
1609}
1610
Michal Vaskoea5abea2018-09-18 13:10:54 +02001611/**
1612 * @brief Parse a restriction such as range or length.
1613 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001614 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001615 * @param[in,out] data Data to read from, always moved to currently handled character.
1616 * @param[in] restr_kw Type of this particular restriction.
1617 * @param[in,out] exts Extension instances to add to.
1618 *
1619 * @return LY_ERR values.
1620 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001621static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001622parse_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 +02001623{
1624 LY_ERR ret = 0;
1625 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001626 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001627 enum yang_keyword kw;
1628
1629 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001630 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001631 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001632
Radek Krejci44ceedc2018-10-02 15:54:31 +02001633 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001634 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001635 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001636
1637 switch (kw) {
1638 case YANG_DESCRIPTION:
1639 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
1640 break;
1641 case YANG_REFERENCE:
1642 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
1643 break;
1644 case YANG_ERROR_APP_TAG:
1645 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
1646 break;
1647 case YANG_ERROR_MESSAGE:
1648 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
1649 break;
1650 case YANG_CUSTOM:
1651 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
1652 break;
1653 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001654 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001655 return LY_EVALID;
1656 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001657 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001658 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001659 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001660
1661 return ret;
1662}
1663
Michal Vaskoea5abea2018-09-18 13:10:54 +02001664/**
1665 * @brief Parse a restriction that can have more instances such as must.
1666 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001667 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001668 * @param[in,out] data Data to read from, always moved to currently handled character.
1669 * @param[in] restr_kw Type of this particular restriction.
1670 * @param[in,out] restrs Restrictions to add 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_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 +02001676{
1677 struct lysp_restr *restr;
1678
1679 LYSP_ARRAY_NEW_RET(ctx, restrs, restr, LY_EMEM);
1680
1681 return parse_restr(ctx, data, restr_kw, restr);
1682}
1683
Michal Vaskoea5abea2018-09-18 13:10:54 +02001684/**
1685 * @brief Parse the status statement.
1686 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001687 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001688 * @param[in,out] data Data to read from, always moved to currently handled character.
1689 * @param[in,out] flags Flags to add to.
1690 * @param[in,out] exts Extension instances to add to.
1691 *
1692 * @return LY_ERR values.
1693 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001694static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001695parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001696{
1697 LY_ERR ret = 0;
1698 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001699 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001700 enum yang_keyword kw;
1701
1702 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001703 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001704 return LY_EVALID;
1705 }
1706
1707 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001708 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001709 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001710
1711 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1712 *flags |= LYS_STATUS_CURR;
1713 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1714 *flags |= LYS_STATUS_DEPRC;
1715 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1716 *flags |= LYS_STATUS_OBSLT;
1717 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001718 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001719 free(buf);
1720 return LY_EVALID;
1721 }
1722 free(buf);
1723
1724 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001725 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001726
1727 switch (kw) {
1728 case YANG_CUSTOM:
1729 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001730 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001731 break;
1732 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001733 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001734 return LY_EVALID;
1735 }
1736 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001737 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001738
1739 return ret;
1740}
1741
Michal Vaskoea5abea2018-09-18 13:10:54 +02001742/**
1743 * @brief Parse the when statement.
1744 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001745 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001746 * @param[in,out] data Data to read from, always moved to currently handled character.
1747 * @param[in,out] when_p When pointer to parse to.
1748 *
1749 * @return LY_ERR values.
1750 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001751static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001752parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001753{
1754 LY_ERR ret = 0;
1755 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001756 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001757 enum yang_keyword kw;
1758 struct lysp_when *when;
1759
1760 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001761 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001762 return LY_EVALID;
1763 }
1764
1765 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001766 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001767 *when_p = when;
1768
1769 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001770 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001771 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001772
Radek Krejci44ceedc2018-10-02 15:54:31 +02001773 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001774 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001775 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001776
1777 switch (kw) {
1778 case YANG_DESCRIPTION:
1779 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts);
1780 break;
1781 case YANG_REFERENCE:
1782 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts);
1783 break;
1784 case YANG_CUSTOM:
1785 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts);
1786 break;
1787 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001788 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001789 return LY_EVALID;
1790 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001791 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001792 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001793 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001794
1795 return ret;
1796}
1797
Michal Vaskoea5abea2018-09-18 13:10:54 +02001798/**
1799 * @brief Parse the anydata or anyxml statement.
1800 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001801 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001802 * @param[in,out] data Data to read from, always moved to currently handled character.
1803 * @param[in] kw Type of this particular keyword.
1804 * @param[in,out] siblings Siblings to add to.
1805 *
1806 * @return LY_ERR values.
1807 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001808static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001809parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001810{
1811 LY_ERR ret = 0;
1812 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001813 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001814 struct lysp_node *iter;
1815 struct lysp_node_anydata *any;
1816
1817 /* create structure */
1818 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001819 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001820 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
1821
1822 /* insert into siblings */
1823 if (!*siblings) {
1824 *siblings = (struct lysp_node *)any;
1825 } else {
1826 for (iter = *siblings; iter->next; iter = iter->next);
1827 iter->next = (struct lysp_node *)any;
1828 }
1829
1830 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001831 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001832 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001833
Radek Krejci44ceedc2018-10-02 15:54:31 +02001834 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001835
1836 /* parse substatements */
1837 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001838 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001839
1840 switch (kw) {
1841 case YANG_CONFIG:
1842 ret = parse_config(ctx, data, &any->flags, &any->exts);
1843 break;
1844 case YANG_DESCRIPTION:
1845 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts);
1846 break;
1847 case YANG_IF_FEATURE:
1848 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts);
1849 break;
1850 case YANG_MANDATORY:
1851 ret = parse_mandatory(ctx, data, &any->flags, &any->exts);
1852 break;
1853 case YANG_MUST:
1854 ret = parse_restrs(ctx, data, kw, &any->musts);
1855 break;
1856 case YANG_REFERENCE:
1857 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts);
1858 break;
1859 case YANG_STATUS:
1860 ret = parse_status(ctx, data, &any->flags, &any->exts);
1861 break;
1862 case YANG_WHEN:
1863 ret = parse_when(ctx, data, &any->when);
1864 break;
1865 case YANG_CUSTOM:
1866 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts);
1867 break;
1868 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001869 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001870 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001871 return LY_EVALID;
1872 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001873 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001874 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001875 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001876
1877 return ret;
1878}
1879
Michal Vaskoea5abea2018-09-18 13:10:54 +02001880/**
1881 * @brief Parse the value or position statement. Substatement of type enum statement.
1882 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001883 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001884 * @param[in,out] data Data to read from, always moved to currently handled character.
1885 * @param[in] val_kw Type of this particular keyword.
1886 * @param[in,out] value Value to write to.
1887 * @param[in,out] flags Flags to write to.
1888 * @param[in,out] exts Extension instances to add to.
1889 *
1890 * @return LY_ERR values.
1891 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001892static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001893parse_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 +02001894 struct lysp_ext_instance **exts)
1895{
1896 LY_ERR ret = 0;
1897 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001898 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001899 long int num;
1900 unsigned long int unum;
1901 enum yang_keyword kw;
1902
1903 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001904 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001905 return LY_EVALID;
1906 }
1907 *flags |= LYS_SET_VALUE;
1908
1909 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001910 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001911 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001912
1913 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 +02001914 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001915 free(buf);
1916 return LY_EVALID;
1917 }
1918
1919 errno = 0;
1920 if (val_kw == YANG_VALUE) {
1921 num = strtol(word, &ptr, 10);
1922 } else {
1923 unum = strtoul(word, &ptr, 10);
1924 }
1925 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001926 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001927 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001928 free(buf);
1929 return LY_EVALID;
1930 }
1931 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001932 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001933 free(buf);
1934 return LY_EVALID;
1935 }
1936 if (val_kw == YANG_VALUE) {
1937 *value = num;
1938 } else {
1939 *value = unum;
1940 }
1941 free(buf);
1942
1943 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001944 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001945
1946 switch (kw) {
1947 case YANG_CUSTOM:
1948 ret = parse_ext(ctx, data, word, word_len, val_kw == YANG_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001949 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001950 break;
1951 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001952 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001953 return LY_EVALID;
1954 }
1955 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001956 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001957
1958 return ret;
1959}
1960
Michal Vaskoea5abea2018-09-18 13:10:54 +02001961/**
1962 * @brief Parse the enum or bit statement. Substatement of type statement.
1963 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001964 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001965 * @param[in,out] data Data to read from, always moved to currently handled character.
1966 * @param[in] enum_kw Type of this particular keyword.
1967 * @param[in,out] enums Enums or bits to add to.
1968 *
1969 * @return LY_ERR values.
1970 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001971static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001972parse_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 +02001973{
1974 LY_ERR ret = 0;
1975 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001976 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001977 enum yang_keyword kw;
1978 struct lysp_type_enum *enm;
1979
1980 LYSP_ARRAY_NEW_RET(ctx, enums, enm, LY_EMEM);
1981
1982 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001983 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001984 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001985
Radek Krejci44ceedc2018-10-02 15:54:31 +02001986 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001987 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001988 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001989
1990 switch (kw) {
1991 case YANG_DESCRIPTION:
1992 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts);
1993 break;
1994 case YANG_IF_FEATURE:
1995 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts);
1996 break;
1997 case YANG_REFERENCE:
1998 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts);
1999 break;
2000 case YANG_STATUS:
2001 ret = parse_status(ctx, data, &enm->flags, &enm->exts);
2002 break;
2003 case YANG_VALUE:
2004 case YANG_POSITION:
2005 ret = parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts);
2006 break;
2007 case YANG_CUSTOM:
2008 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts);
2009 break;
2010 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002011 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002012 return LY_EVALID;
2013 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002014 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002015 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002016 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002017
2018 return ret;
2019}
2020
Michal Vaskoea5abea2018-09-18 13:10:54 +02002021/**
2022 * @brief Parse the fraction-digits statement. Substatement of type statement.
2023 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002024 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002025 * @param[in,out] data Data to read from, always moved to currently handled character.
2026 * @param[in,out] fracdig Value to write to.
2027 * @param[in,out] exts Extension instances to add to.
2028 *
2029 * @return LY_ERR values.
2030 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002031static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002032parse_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 +02002033{
2034 LY_ERR ret = 0;
2035 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002036 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002037 unsigned long int num;
2038 enum yang_keyword kw;
2039
2040 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002041 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002042 return LY_EVALID;
2043 }
2044
2045 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002046 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002047 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002048
2049 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002050 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002051 free(buf);
2052 return LY_EVALID;
2053 }
2054
2055 errno = 0;
2056 num = strtoul(word, &ptr, 10);
2057 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002058 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002059 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002060 free(buf);
2061 return LY_EVALID;
2062 }
2063 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002064 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002065 free(buf);
2066 return LY_EVALID;
2067 }
2068 *fracdig = num;
2069 free(buf);
2070
2071 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002072 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002073
2074 switch (kw) {
2075 case YANG_CUSTOM:
2076 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002077 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002078 break;
2079 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002080 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002081 return LY_EVALID;
2082 }
2083 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002084 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002085
2086 return ret;
2087}
2088
Michal Vaskoea5abea2018-09-18 13:10:54 +02002089/**
2090 * @brief Parse the require-instance 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] reqinst Value to write to.
2095 * @param[in,out] flags Flags to write to.
2096 * @param[in,out] exts Extension instances to add to.
2097 *
2098 * @return LY_ERR values.
2099 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002100static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002101parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002102 struct lysp_ext_instance **exts)
2103{
2104 LY_ERR ret = 0;
2105 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002106 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002107 enum yang_keyword kw;
2108
2109 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002110 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002111 return LY_EVALID;
2112 }
2113 *flags |= LYS_SET_REQINST;
2114
2115 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002116 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002117 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002118
2119 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2120 *reqinst = 1;
2121 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002122 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002123 free(buf);
2124 return LY_EVALID;
2125 }
2126 free(buf);
2127
2128 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002129 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002130
2131 switch (kw) {
2132 case YANG_CUSTOM:
2133 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002134 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002135 break;
2136 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002137 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002138 return LY_EVALID;
2139 }
2140 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002141 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002142
2143 return ret;
2144}
2145
Michal Vaskoea5abea2018-09-18 13:10:54 +02002146/**
2147 * @brief Parse the modifier statement. Substatement of type pattern statement.
2148 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002149 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002150 * @param[in,out] data Data to read from, always moved to currently handled character.
2151 * @param[in,out] pat Value to write to.
2152 * @param[in,out] exts Extension instances to add to.
2153 *
2154 * @return LY_ERR values.
2155 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002156static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002157parse_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 +02002158{
2159 LY_ERR ret = 0;
2160 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002161 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002162 enum yang_keyword kw;
2163
2164 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002165 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002166 return LY_EVALID;
2167 }
2168
2169 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002170 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002171 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002172
2173 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002174 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002175 free(buf);
2176 return LY_EVALID;
2177 }
2178 free(buf);
2179
2180 /* replace the value in the dictionary */
2181 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002182 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002183 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002184 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002185
2186 assert(buf[0] == 0x06);
2187 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002188 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189
2190 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002191 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002192
2193 switch (kw) {
2194 case YANG_CUSTOM:
2195 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002196 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002197 break;
2198 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002199 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002200 return LY_EVALID;
2201 }
2202 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002203 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002204
2205 return ret;
2206}
2207
Michal Vaskoea5abea2018-09-18 13:10:54 +02002208/**
2209 * @brief Parse the pattern statement. Substatement of type statement.
2210 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002211 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002212 * @param[in,out] data Data to read from, always moved to currently handled character.
2213 * @param[in,out] patterns Restrictions to add to.
2214 *
2215 * @return LY_ERR values.
2216 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002217static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002218parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002219{
2220 LY_ERR ret = 0;
2221 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002222 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002223 enum yang_keyword kw;
2224 struct lysp_restr *restr;
2225
2226 LYSP_ARRAY_NEW_RET(ctx, patterns, restr, LY_EMEM);
2227
2228 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002229 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002230 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002231
2232 /* add special meaning first byte */
2233 if (buf) {
2234 buf = realloc(buf, word_len + 2);
2235 word = buf;
2236 } else {
2237 buf = malloc(word_len + 2);
2238 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002239 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002240 memmove(buf + 1, word, word_len + 1);
2241 word[0] = 0x06;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002242 restr->arg = lydict_insert_zc(ctx->ctx, word);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002243
2244 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002245 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002246
2247 switch (kw) {
2248 case YANG_DESCRIPTION:
2249 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
2250 break;
2251 case YANG_REFERENCE:
2252 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
2253 break;
2254 case YANG_ERROR_APP_TAG:
2255 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
2256 break;
2257 case YANG_ERROR_MESSAGE:
2258 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
2259 break;
2260 case YANG_MODIFIER:
2261 ret = parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts);
2262 break;
2263 case YANG_CUSTOM:
2264 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
2265 break;
2266 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002267 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002268 return LY_EVALID;
2269 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002270 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002271 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002272 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002273
2274 return ret;
2275}
2276
Michal Vaskoea5abea2018-09-18 13:10:54 +02002277/**
2278 * @brief Parse the type statement.
2279 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002280 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002281 * @param[in,out] data Data to read from, always moved to currently handled character.
2282 * @param[in,out] type Type to wrote to.
2283 *
2284 * @return LY_ERR values.
2285 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002286static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002287parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002288{
2289 LY_ERR ret = 0;
2290 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002291 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002292 enum yang_keyword kw;
2293 struct lysp_type *nest_type;
2294
2295 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002296 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002297 return LY_EVALID;
2298 }
2299
2300 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002301 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002302 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002303
Radek Krejci44ceedc2018-10-02 15:54:31 +02002304 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002305 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002306 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002307
2308 switch (kw) {
2309 case YANG_BASE:
2310 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts);
2311 break;
2312 case YANG_BIT:
2313 ret = parse_type_enum(ctx, data, kw, &type->bits);
2314 break;
2315 case YANG_ENUM:
2316 ret = parse_type_enum(ctx, data, kw, &type->enums);
2317 break;
2318 case YANG_FRACTION_DIGITS:
2319 ret = parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts);
2320 break;
2321 case YANG_LENGTH:
2322 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002323 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002324 return LY_EVALID;
2325 }
2326 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002327 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002328
2329 ret = parse_restr(ctx, data, kw, type->length);
2330 break;
2331 case YANG_PATH:
2332 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts);
2333 break;
2334 case YANG_PATTERN:
2335 ret = parse_type_pattern(ctx, data, &type->patterns);
2336 break;
2337 case YANG_RANGE:
2338 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002339 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002340 return LY_EVALID;
2341 }
2342 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002343 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002344
2345 ret = parse_restr(ctx, data, kw, type->range);
2346 break;
2347 case YANG_REQUIRE_INSTANCE:
2348 ret = parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts);
2349 break;
2350 case YANG_TYPE:
2351 {
2352 LYSP_ARRAY_NEW_RET(ctx, &type->types, nest_type, LY_EMEM);
2353 }
2354 ret = parse_type(ctx, data, nest_type);
2355 break;
2356 case YANG_CUSTOM:
2357 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts);
2358 break;
2359 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002360 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002361 return LY_EVALID;
2362 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002363 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002364 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002365 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002366
2367 return ret;
2368}
2369
Michal Vaskoea5abea2018-09-18 13:10:54 +02002370/**
2371 * @brief Parse the leaf statement.
2372 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002373 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002374 * @param[in,out] data Data to read from, always moved to currently handled character.
2375 * @param[in,out] siblings Siblings to add to.
2376 *
2377 * @return LY_ERR values.
2378 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002379static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002380parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002381{
2382 LY_ERR ret = 0;
2383 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002384 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002385 enum yang_keyword kw;
2386 struct lysp_node *iter;
2387 struct lysp_node_leaf *leaf;
2388
2389 /* create structure */
2390 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002391 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002392 leaf->nodetype = LYS_LEAF;
2393
2394 /* insert into siblings */
2395 if (!*siblings) {
2396 *siblings = (struct lysp_node *)leaf;
2397 } else {
2398 for (iter = *siblings; iter->next; iter = iter->next);
2399 iter->next = (struct lysp_node *)leaf;
2400 }
2401
2402 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002403 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002404 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002405
Radek Krejci44ceedc2018-10-02 15:54:31 +02002406 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002407
2408 /* parse substatements */
2409 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002410 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002411
2412 switch (kw) {
2413 case YANG_CONFIG:
2414 ret = parse_config(ctx, data, &leaf->flags, &leaf->exts);
2415 break;
2416 case YANG_DEFAULT:
2417 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts);
2418 break;
2419 case YANG_DESCRIPTION:
2420 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts);
2421 break;
2422 case YANG_IF_FEATURE:
2423 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts);
2424 break;
2425 case YANG_MANDATORY:
2426 ret = parse_mandatory(ctx, data, &leaf->flags, &leaf->exts);
2427 break;
2428 case YANG_MUST:
2429 ret = parse_restrs(ctx, data, kw, &leaf->musts);
2430 break;
2431 case YANG_REFERENCE:
2432 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts);
2433 break;
2434 case YANG_STATUS:
2435 ret = parse_status(ctx, data, &leaf->flags, &leaf->exts);
2436 break;
2437 case YANG_TYPE:
2438 ret = parse_type(ctx, data, &leaf->type);
2439 break;
2440 case YANG_UNITS:
2441 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts);
2442 break;
2443 case YANG_WHEN:
2444 ret = parse_when(ctx, data, &leaf->when);
2445 break;
2446 case YANG_CUSTOM:
2447 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts);
2448 break;
2449 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002450 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002451 return LY_EVALID;
2452 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002453 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002454 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002455 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002456
2457 /* mandatory substatements */
2458 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002459 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002460 return LY_EVALID;
2461 }
2462
2463 return ret;
2464}
2465
Michal Vaskoea5abea2018-09-18 13:10:54 +02002466/**
2467 * @brief Parse the max-elements statement.
2468 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002469 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002470 * @param[in,out] data Data to read from, always moved to currently handled character.
2471 * @param[in,out] max Value to write to.
2472 * @param[in,out] flags Flags to write to.
2473 * @param[in,out] exts Extension instances to add to.
2474 *
2475 * @return LY_ERR values.
2476 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002477static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002478parse_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 +02002479{
2480 LY_ERR ret = 0;
2481 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002482 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002483 unsigned long int num;
2484 enum yang_keyword kw;
2485
2486 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002487 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002488 return LY_EVALID;
2489 }
2490 *flags |= LYS_SET_MAX;
2491
2492 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002493 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002494 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002495
2496 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002497 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002498 free(buf);
2499 return LY_EVALID;
2500 }
2501
2502 if (strncmp(word, "unbounded", word_len)) {
2503 errno = 0;
2504 num = strtoul(word, &ptr, 10);
2505 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002506 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002507 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002508 free(buf);
2509 return LY_EVALID;
2510 }
2511 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002512 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002513 free(buf);
2514 return LY_EVALID;
2515 }
2516
2517 *max = num;
2518 }
2519 free(buf);
2520
2521 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002522 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002523
2524 switch (kw) {
2525 case YANG_CUSTOM:
2526 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002527 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002528 break;
2529 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002530 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002531 return LY_EVALID;
2532 }
2533 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002534 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002535
2536 return ret;
2537}
2538
Michal Vaskoea5abea2018-09-18 13:10:54 +02002539/**
2540 * @brief Parse the min-elements statement.
2541 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002542 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002543 * @param[in,out] data Data to read from, always moved to currently handled character.
2544 * @param[in,out] min Value to write to.
2545 * @param[in,out] flags Flags to write to.
2546 * @param[in,out] exts Extension instances to add to.
2547 *
2548 * @return LY_ERR values.
2549 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002550static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002551parse_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 +02002552{
2553 LY_ERR ret = 0;
2554 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002555 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002556 unsigned long int num;
2557 enum yang_keyword kw;
2558
2559 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002560 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002561 return LY_EVALID;
2562 }
2563 *flags |= LYS_SET_MIN;
2564
2565 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002566 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002567 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002568
2569 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002570 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002571 free(buf);
2572 return LY_EVALID;
2573 }
2574
2575 errno = 0;
2576 num = strtoul(word, &ptr, 10);
2577 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002578 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002579 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002580 free(buf);
2581 return LY_EVALID;
2582 }
2583 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002584 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002585 free(buf);
2586 return LY_EVALID;
2587 }
2588 *min = num;
2589 free(buf);
2590
2591 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002592 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002593
2594 switch (kw) {
2595 case YANG_CUSTOM:
2596 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002597 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002598 break;
2599 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002600 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002601 return LY_EVALID;
2602 }
2603 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002604 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002605
2606 return ret;
2607}
2608
Michal Vaskoea5abea2018-09-18 13:10:54 +02002609/**
2610 * @brief Parse the ordered-by statement.
2611 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002612 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002613 * @param[in,out] data Data to read from, always moved to currently handled character.
2614 * @param[in,out] flags Flags to write to.
2615 * @param[in,out] exts Extension instances to add to.
2616 *
2617 * @return LY_ERR values.
2618 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002619static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002620parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002621{
2622 LY_ERR ret = 0;
2623 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002624 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002625 enum yang_keyword kw;
2626
2627 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002628 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002629 return LY_EVALID;
2630 }
2631
2632 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002633 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002634 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002635
2636 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2637 *flags |= LYS_ORDBY_SYSTEM;
2638 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2639 *flags |= LYS_ORDBY_USER;
2640 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002641 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002642 free(buf);
2643 return LY_EVALID;
2644 }
2645 free(buf);
2646
2647 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002648 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002649
2650 switch (kw) {
2651 case YANG_CUSTOM:
2652 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002653 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002654 break;
2655 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002656 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002657 return LY_EVALID;
2658 }
2659 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002660 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002661
2662 return ret;
2663}
2664
Michal Vaskoea5abea2018-09-18 13:10:54 +02002665/**
2666 * @brief Parse the leaf-list statement.
2667 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002668 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002669 * @param[in,out] data Data to read from, always moved to currently handled character.
2670 * @param[in,out] siblings Siblings to add to.
2671 *
2672 * @return LY_ERR values.
2673 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002674static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002675parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002676{
2677 LY_ERR ret = 0;
2678 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002679 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002680 enum yang_keyword kw;
2681 struct lysp_node *iter;
2682 struct lysp_node_leaflist *llist;
2683
2684 /* create structure */
2685 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002686 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002687 llist->nodetype = LYS_LEAFLIST;
2688
2689 /* insert into siblings */
2690 if (!*siblings) {
2691 *siblings = (struct lysp_node *)llist;
2692 } else {
2693 for (iter = *siblings; iter->next; iter = iter->next);
2694 iter->next = (struct lysp_node *)llist;
2695 }
2696
2697 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002698 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002699 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002700
Radek Krejci44ceedc2018-10-02 15:54:31 +02002701 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002702
2703 /* parse substatements */
2704 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002705 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002706
2707 switch (kw) {
2708 case YANG_CONFIG:
2709 ret = parse_config(ctx, data, &llist->flags, &llist->exts);
2710 break;
2711 case YANG_DEFAULT:
2712 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts);
2713 break;
2714 case YANG_DESCRIPTION:
2715 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts);
2716 break;
2717 case YANG_IF_FEATURE:
2718 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts);
2719 break;
2720 case YANG_MAX_ELEMENTS:
2721 ret = parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts);
2722 break;
2723 case YANG_MIN_ELEMENTS:
2724 ret = parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts);
2725 break;
2726 case YANG_MUST:
2727 ret = parse_restrs(ctx, data, kw, &llist->musts);
2728 break;
2729 case YANG_ORDERED_BY:
2730 ret = parse_orderedby(ctx, data, &llist->flags, &llist->exts);
2731 break;
2732 case YANG_REFERENCE:
2733 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts);
2734 break;
2735 case YANG_STATUS:
2736 ret = parse_status(ctx, data, &llist->flags, &llist->exts);
2737 break;
2738 case YANG_TYPE:
2739 ret = parse_type(ctx, data, &llist->type);
2740 break;
2741 case YANG_UNITS:
2742 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts);
2743 break;
2744 case YANG_WHEN:
2745 ret = parse_when(ctx, data, &llist->when);
2746 break;
2747 case YANG_CUSTOM:
2748 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts);
2749 break;
2750 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002751 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002752 return LY_EVALID;
2753 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002754 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002755 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002756 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002757
2758 /* mandatory substatements */
2759 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002760 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002761 return LY_EVALID;
2762 }
2763
2764 return ret;
2765}
2766
Michal Vaskoea5abea2018-09-18 13:10:54 +02002767/**
2768 * @brief Parse the refine statement.
2769 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002770 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002771 * @param[in,out] data Data to read from, always moved to currently handled character.
2772 * @param[in,out] refines Refines to add to.
2773 *
2774 * @return LY_ERR values.
2775 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002776static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002777parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002778{
2779 LY_ERR ret = 0;
2780 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002781 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002782 enum yang_keyword kw;
2783 struct lysp_refine *rf;
2784
2785 LYSP_ARRAY_NEW_RET(ctx, refines, rf, LY_EMEM);
2786
2787 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002788 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002789 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790
Radek Krejci44ceedc2018-10-02 15:54:31 +02002791 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002792 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002793 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002794
2795 switch (kw) {
2796 case YANG_CONFIG:
2797 ret = parse_config(ctx, data, &rf->flags, &rf->exts);
2798 break;
2799 case YANG_DEFAULT:
2800 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts);
2801 break;
2802 case YANG_DESCRIPTION:
2803 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts);
2804 break;
2805 case YANG_IF_FEATURE:
2806 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts);
2807 break;
2808 case YANG_MAX_ELEMENTS:
2809 ret = parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts);
2810 break;
2811 case YANG_MIN_ELEMENTS:
2812 ret = parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts);
2813 break;
2814 case YANG_MUST:
2815 ret = parse_restrs(ctx, data, kw, &rf->musts);
2816 break;
2817 case YANG_MANDATORY:
2818 ret = parse_mandatory(ctx, data, &rf->flags, &rf->exts);
2819 break;
2820 case YANG_REFERENCE:
2821 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts);
2822 break;
2823 case YANG_PRESENCE:
2824 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts);
2825 break;
2826 case YANG_CUSTOM:
2827 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts);
2828 break;
2829 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002830 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002831 return LY_EVALID;
2832 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002833 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002834 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002835 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002836
2837 return ret;
2838}
2839
Michal Vaskoea5abea2018-09-18 13:10:54 +02002840/**
2841 * @brief Parse the typedef statement.
2842 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002843 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002844 * @param[in,out] data Data to read from, always moved to currently handled character.
2845 * @param[in,out] typedefs Typedefs to add to.
2846 *
2847 * @return LY_ERR values.
2848 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002849static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002850parse_typedef(struct ly_parser_ctx *ctx, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002851{
2852 LY_ERR ret = 0;
2853 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002854 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002855 enum yang_keyword kw;
2856 struct lysp_tpdf *tpdf;
2857
2858 LYSP_ARRAY_NEW_RET(ctx, typedefs, tpdf, LY_EMEM);
2859
2860 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002861 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002862 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863
Radek Krejci44ceedc2018-10-02 15:54:31 +02002864 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002865
2866 /* parse substatements */
2867 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002868 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002869
2870 switch (kw) {
2871 case YANG_DEFAULT:
2872 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts);
2873 break;
2874 case YANG_DESCRIPTION:
2875 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts);
2876 break;
2877 case YANG_REFERENCE:
2878 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts);
2879 break;
2880 case YANG_STATUS:
2881 ret = parse_status(ctx, data, &tpdf->flags, &tpdf->exts);
2882 break;
2883 case YANG_TYPE:
2884 ret = parse_type(ctx, data, &tpdf->type);
2885 break;
2886 case YANG_UNITS:
2887 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts);
2888 break;
2889 case YANG_CUSTOM:
2890 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts);
2891 break;
2892 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002893 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002894 return LY_EVALID;
2895 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002896 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002897 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002898 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002899
2900 /* mandatory substatements */
2901 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002902 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002903 return LY_EVALID;
2904 }
2905
2906 return ret;
2907}
2908
Michal Vaskoea5abea2018-09-18 13:10:54 +02002909/**
2910 * @brief Parse the input or output statement.
2911 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002912 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002913 * @param[in,out] data Data to read from, always moved to currently handled character.
2914 * @param[in] kw Type of this particular keyword
2915 * @param[in,out] inout_p Input/output pointer to write to.
2916 *
2917 * @return LY_ERR values.
2918 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002919static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002920parse_inout(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_action_inout **inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002921{
2922 LY_ERR ret = 0;
2923 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002924 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002925 struct lysp_action_inout *inout;
2926
2927 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002928 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002929 return LY_EVALID;
2930 }
2931
2932 /* create structure */
2933 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002934 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002935 *inout_p = inout;
2936
2937 /* parse substatements */
2938 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002939 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002940
2941 switch (kw) {
2942 case YANG_ANYDATA:
2943 case YANG_ANYXML:
2944 ret = parse_any(ctx, data, kw, &inout->data);
2945 break;
2946 case YANG_CHOICE:
2947 ret = parse_choice(ctx, data, &inout->data);
2948 break;
2949 case YANG_CONTAINER:
2950 ret = parse_container(ctx, data, &inout->data);
2951 break;
2952 case YANG_LEAF:
2953 ret = parse_leaf(ctx, data, &inout->data);
2954 break;
2955 case YANG_LEAF_LIST:
2956 ret = parse_leaflist(ctx, data, &inout->data);
2957 break;
2958 case YANG_LIST:
2959 ret = parse_list(ctx, data, &inout->data);
2960 break;
2961 case YANG_USES:
2962 ret = parse_uses(ctx, data, &inout->data);
2963 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002964 case YANG_TYPEDEF:
2965 ret = parse_typedef(ctx, data, &inout->typedefs);
2966 break;
2967 case YANG_MUST:
2968 ret = parse_restrs(ctx, data, kw, &inout->musts);
2969 break;
2970 case YANG_GROUPING:
2971 ret = parse_grouping(ctx, data, &inout->groupings);
2972 break;
2973 case YANG_CUSTOM:
2974 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts);
2975 break;
2976 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002977 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978 return LY_EVALID;
2979 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002980 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002981 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002982 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002983
2984 return ret;
2985}
2986
Michal Vaskoea5abea2018-09-18 13:10:54 +02002987/**
2988 * @brief Parse the action statement.
2989 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002990 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002991 * @param[in,out] data Data to read from, always moved to currently handled character.
2992 * @param[in,out] actions Actions to add to.
2993 *
2994 * @return LY_ERR values.
2995 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002996static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002997parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002998{
2999 LY_ERR ret = 0;
3000 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003001 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003002 enum yang_keyword kw;
3003 struct lysp_action *act;
3004
3005 LYSP_ARRAY_NEW_RET(ctx, actions, act, LY_EMEM);
3006
3007 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003008 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003009 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003010
Radek Krejci44ceedc2018-10-02 15:54:31 +02003011 INSERT_WORD(ctx, buf, act->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003012 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003013 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003014
3015 switch (kw) {
3016 case YANG_DESCRIPTION:
3017 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts);
3018 break;
3019 case YANG_IF_FEATURE:
3020 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts);
3021 break;
3022 case YANG_REFERENCE:
3023 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts);
3024 break;
3025 case YANG_STATUS:
3026 ret = parse_status(ctx, data, &act->flags, &act->exts);
3027 break;
3028
3029 case YANG_INPUT:
3030 ret = parse_inout(ctx, data, kw, &act->input);
3031 break;
3032 case YANG_OUTPUT:
3033 ret = parse_inout(ctx, data, kw, &act->output);
3034 break;
3035
3036 case YANG_TYPEDEF:
3037 ret = parse_typedef(ctx, data, &act->typedefs);
3038 break;
3039 case YANG_GROUPING:
3040 ret = parse_grouping(ctx, data, &act->groupings);
3041 break;
3042 case YANG_CUSTOM:
3043 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts);
3044 break;
3045 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003046 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003047 return LY_EVALID;
3048 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003049 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003050 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003051 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003052
3053 return ret;
3054}
3055
Michal Vaskoea5abea2018-09-18 13:10:54 +02003056/**
3057 * @brief Parse the notification statement.
3058 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003059 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003060 * @param[in,out] data Data to read from, always moved to currently handled character.
3061 * @param[in,out] notifs Notifications to add to.
3062 *
3063 * @return LY_ERR values.
3064 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003065static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003066parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003067{
3068 LY_ERR ret = 0;
3069 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003070 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003071 enum yang_keyword kw;
3072 struct lysp_notif *notif;
3073
3074 LYSP_ARRAY_NEW_RET(ctx, notifs, notif, LY_EMEM);
3075
3076 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003077 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003078 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003079
Radek Krejci44ceedc2018-10-02 15:54:31 +02003080 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003081 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003082 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003083
3084 switch (kw) {
3085 case YANG_DESCRIPTION:
3086 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts);
3087 break;
3088 case YANG_IF_FEATURE:
3089 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts);
3090 break;
3091 case YANG_REFERENCE:
3092 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts);
3093 break;
3094 case YANG_STATUS:
3095 ret = parse_status(ctx, data, &notif->flags, &notif->exts);
3096 break;
3097
3098 case YANG_ANYDATA:
3099 case YANG_ANYXML:
3100 ret = parse_any(ctx, data, kw, &notif->data);
3101 break;
3102 case YANG_CHOICE:
3103 ret = parse_case(ctx, data, &notif->data);
3104 break;
3105 case YANG_CONTAINER:
3106 ret = parse_container(ctx, data, &notif->data);
3107 break;
3108 case YANG_LEAF:
3109 ret = parse_leaf(ctx, data, &notif->data);
3110 break;
3111 case YANG_LEAF_LIST:
3112 ret = parse_leaflist(ctx, data, &notif->data);
3113 break;
3114 case YANG_LIST:
3115 ret = parse_list(ctx, data, &notif->data);
3116 break;
3117 case YANG_USES:
3118 ret = parse_uses(ctx, data, &notif->data);
3119 break;
3120
3121 case YANG_MUST:
3122 ret = parse_restrs(ctx, data, kw, &notif->musts);
3123 break;
3124 case YANG_TYPEDEF:
3125 ret = parse_typedef(ctx, data, &notif->typedefs);
3126 break;
3127 case YANG_GROUPING:
3128 ret = parse_grouping(ctx, data, &notif->groupings);
3129 break;
3130 case YANG_CUSTOM:
3131 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts);
3132 break;
3133 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003134 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135 return LY_EVALID;
3136 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003137 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003138 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003139 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003140
3141 return ret;
3142}
3143
Michal Vaskoea5abea2018-09-18 13:10:54 +02003144/**
3145 * @brief Parse the grouping 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] groupings Groupings to add to.
3150 *
3151 * @return LY_ERR values.
3152 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003153static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003154parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003155{
3156 LY_ERR ret = 0;
3157 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_grp *grp;
3161
3162 LYSP_ARRAY_NEW_RET(ctx, groupings, grp, LY_EMEM);
3163
3164 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003165 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003166 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003167
Radek Krejci44ceedc2018-10-02 15:54:31 +02003168 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003169
3170 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003171 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003172
3173 switch (kw) {
3174 case YANG_DESCRIPTION:
3175 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts);
3176 break;
3177 case YANG_REFERENCE:
3178 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts);
3179 break;
3180 case YANG_STATUS:
3181 ret = parse_status(ctx, data, &grp->flags, &grp->exts);
3182 break;
3183
3184 case YANG_ANYDATA:
3185 case YANG_ANYXML:
3186 ret = parse_any(ctx, data, kw, &grp->data);
3187 break;
3188 case YANG_CHOICE:
3189 ret = parse_choice(ctx, data, &grp->data);
3190 break;
3191 case YANG_CONTAINER:
3192 ret = parse_container(ctx, data, &grp->data);
3193 break;
3194 case YANG_LEAF:
3195 ret = parse_leaf(ctx, data, &grp->data);
3196 break;
3197 case YANG_LEAF_LIST:
3198 ret = parse_leaflist(ctx, data, &grp->data);
3199 break;
3200 case YANG_LIST:
3201 ret = parse_list(ctx, data, &grp->data);
3202 break;
3203 case YANG_USES:
3204 ret = parse_uses(ctx, data, &grp->data);
3205 break;
3206
3207 case YANG_TYPEDEF:
3208 ret = parse_typedef(ctx, data, &grp->typedefs);
3209 break;
3210 case YANG_ACTION:
3211 ret = parse_action(ctx, data, &grp->actions);
3212 break;
3213 case YANG_GROUPING:
3214 ret = parse_grouping(ctx, data, &grp->groupings);
3215 break;
3216 case YANG_NOTIFICATION:
3217 ret = parse_notif(ctx, data, &grp->notifs);
3218 break;
3219 case YANG_CUSTOM:
3220 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts);
3221 break;
3222 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003223 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224 return LY_EVALID;
3225 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003226 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003227 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003228 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003229
3230 return ret;
3231}
3232
Michal Vaskoea5abea2018-09-18 13:10:54 +02003233/**
3234 * @brief Parse the refine statement.
3235 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003236 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003237 * @param[in,out] data Data to read from, always moved to currently handled character.
3238 * @param[in,out] augments Augments to add to.
3239 *
3240 * @return LY_ERR values.
3241 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003242static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003243parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003244{
3245 LY_ERR ret = 0;
3246 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003247 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003248 enum yang_keyword kw;
3249 struct lysp_augment *aug;
3250
3251 LYSP_ARRAY_NEW_RET(ctx, augments, aug, LY_EMEM);
3252
3253 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003254 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003255 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003256
Radek Krejci44ceedc2018-10-02 15:54:31 +02003257 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003258 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003259 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003260
3261 switch (kw) {
3262 case YANG_DESCRIPTION:
3263 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts);
3264 break;
3265 case YANG_IF_FEATURE:
3266 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts);
3267 break;
3268 case YANG_REFERENCE:
3269 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts);
3270 break;
3271 case YANG_STATUS:
3272 ret = parse_status(ctx, data, &aug->flags, &aug->exts);
3273 break;
3274 case YANG_WHEN:
3275 ret = parse_when(ctx, data, &aug->when);
3276 break;
3277
3278 case YANG_ANYDATA:
3279 case YANG_ANYXML:
3280 ret = parse_any(ctx, data, kw, &aug->child);
3281 break;
3282 case YANG_CASE:
3283 ret = parse_case(ctx, data, &aug->child);
3284 break;
3285 case YANG_CHOICE:
3286 ret = parse_choice(ctx, data, &aug->child);
3287 break;
3288 case YANG_CONTAINER:
3289 ret = parse_container(ctx, data, &aug->child);
3290 break;
3291 case YANG_LEAF:
3292 ret = parse_leaf(ctx, data, &aug->child);
3293 break;
3294 case YANG_LEAF_LIST:
3295 ret = parse_leaflist(ctx, data, &aug->child);
3296 break;
3297 case YANG_LIST:
3298 ret = parse_list(ctx, data, &aug->child);
3299 break;
3300 case YANG_USES:
3301 ret = parse_uses(ctx, data, &aug->child);
3302 break;
3303
3304 case YANG_ACTION:
3305 ret = parse_action(ctx, data, &aug->actions);
3306 break;
3307 case YANG_NOTIFICATION:
3308 ret = parse_notif(ctx, data, &aug->notifs);
3309 break;
3310 case YANG_CUSTOM:
3311 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts);
3312 break;
3313 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003314 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003315 return LY_EVALID;
3316 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003317 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003318 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003319 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003320
3321 return ret;
3322}
3323
Michal Vaskoea5abea2018-09-18 13:10:54 +02003324/**
3325 * @brief Parse the uses statement.
3326 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003327 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003328 * @param[in,out] data Data to read from, always moved to currently handled character.
3329 * @param[in,out] siblings Siblings to add to.
3330 *
3331 * @return LY_ERR values.
3332 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003333static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003334parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003335{
3336 LY_ERR ret = 0;
3337 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003338 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003339 enum yang_keyword kw;
3340 struct lysp_node *iter;
3341 struct lysp_node_uses *uses;
3342
3343 /* create structure */
3344 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003345 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003346 uses->nodetype = LYS_USES;
3347
3348 /* insert into siblings */
3349 if (!*siblings) {
3350 *siblings = (struct lysp_node *)uses;
3351 } else {
3352 for (iter = *siblings; iter->next; iter = iter->next);
3353 iter->next = (struct lysp_node *)uses;
3354 }
3355
3356 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003357 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003358 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003359
Radek Krejci44ceedc2018-10-02 15:54:31 +02003360 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003361
3362 /* parse substatements */
3363 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003364 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003365
3366 switch (kw) {
3367 case YANG_DESCRIPTION:
3368 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts);
3369 break;
3370 case YANG_IF_FEATURE:
3371 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts);
3372 break;
3373 case YANG_REFERENCE:
3374 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts);
3375 break;
3376 case YANG_STATUS:
3377 ret = parse_status(ctx, data, &uses->flags, &uses->exts);
3378 break;
3379 case YANG_WHEN:
3380 ret = parse_when(ctx, data, &uses->when);
3381 break;
3382
3383 case YANG_REFINE:
3384 ret = parse_refine(ctx, data, &uses->refines);
3385 break;
3386 case YANG_AUGMENT:
3387 ret = parse_augment(ctx, data, &uses->augments);
3388 break;
3389 case YANG_CUSTOM:
3390 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts);
3391 break;
3392 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003393 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003394 return LY_EVALID;
3395 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003396 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003397 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003398 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003399
3400 return ret;
3401}
3402
Michal Vaskoea5abea2018-09-18 13:10:54 +02003403/**
3404 * @brief Parse the case statement.
3405 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003406 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003407 * @param[in,out] data Data to read from, always moved to currently handled character.
3408 * @param[in,out] siblings Siblings to add to.
3409 *
3410 * @return LY_ERR values.
3411 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003412static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003413parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003414{
3415 LY_ERR ret = 0;
3416 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003417 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003418 enum yang_keyword kw;
3419 struct lysp_node *iter;
3420 struct lysp_node_case *cas;
3421
3422 /* create structure */
3423 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003424 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003425 cas->nodetype = LYS_CASE;
3426
3427 /* insert into siblings */
3428 if (!*siblings) {
3429 *siblings = (struct lysp_node *)cas;
3430 } else {
3431 for (iter = *siblings; iter->next; iter = iter->next);
3432 iter->next = (struct lysp_node *)cas;
3433 }
3434
3435 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003436 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003437 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003438
Radek Krejci44ceedc2018-10-02 15:54:31 +02003439 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003440
3441 /* parse substatements */
3442 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003443 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003444
3445 switch (kw) {
3446 case YANG_DESCRIPTION:
3447 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts);
3448 break;
3449 case YANG_IF_FEATURE:
3450 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts);
3451 break;
3452 case YANG_REFERENCE:
3453 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts);
3454 break;
3455 case YANG_STATUS:
3456 ret = parse_status(ctx, data, &cas->flags, &cas->exts);
3457 break;
3458 case YANG_WHEN:
3459 ret = parse_when(ctx, data, &cas->when);
3460 break;
3461
3462 case YANG_ANYDATA:
3463 case YANG_ANYXML:
3464 ret = parse_any(ctx, data, kw, &cas->child);
3465 break;
3466 case YANG_CHOICE:
3467 ret = parse_case(ctx, data, &cas->child);
3468 break;
3469 case YANG_CONTAINER:
3470 ret = parse_container(ctx, data, &cas->child);
3471 break;
3472 case YANG_LEAF:
3473 ret = parse_leaf(ctx, data, &cas->child);
3474 break;
3475 case YANG_LEAF_LIST:
3476 ret = parse_leaflist(ctx, data, &cas->child);
3477 break;
3478 case YANG_LIST:
3479 ret = parse_list(ctx, data, &cas->child);
3480 break;
3481 case YANG_USES:
3482 ret = parse_uses(ctx, data, &cas->child);
3483 break;
3484 case YANG_CUSTOM:
3485 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts);
3486 break;
3487 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003488 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003489 return LY_EVALID;
3490 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003491 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003492 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003493 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003494
3495 return ret;
3496}
3497
Michal Vaskoea5abea2018-09-18 13:10:54 +02003498/**
3499 * @brief Parse the choice statement.
3500 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003501 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003502 * @param[in,out] data Data to read from, always moved to currently handled character.
3503 * @param[in,out] siblings Siblings to add to.
3504 *
3505 * @return LY_ERR values.
3506 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003507static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003508parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003509{
3510 LY_ERR ret = 0;
3511 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003512 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003513 enum yang_keyword kw;
3514 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003515 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003516
3517 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003518 choice = calloc(1, sizeof *choice);
3519 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3520 choice->nodetype = LYS_CHOICE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003521
3522 /* insert into siblings */
3523 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003524 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003525 } else {
3526 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003527 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003528 }
3529
3530 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003531 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003532 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003533
Radek Krejci44ceedc2018-10-02 15:54:31 +02003534 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003535
3536 /* parse substatements */
3537 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003538 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003539
3540 switch (kw) {
3541 case YANG_CONFIG:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003542 ret = parse_config(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543 break;
3544 case YANG_DESCRIPTION:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003545 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003546 break;
3547 case YANG_IF_FEATURE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003548 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003549 break;
3550 case YANG_MANDATORY:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003551 ret = parse_mandatory(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003552 break;
3553 case YANG_REFERENCE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003554 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003555 break;
3556 case YANG_STATUS:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003557 ret = parse_status(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003558 break;
3559 case YANG_WHEN:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003560 ret = parse_when(ctx, data, &choice->when);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003561 break;
3562 case YANG_DEFAULT:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003563 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_IDENTIF_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003564 break;
3565
3566 case YANG_ANYDATA:
3567 case YANG_ANYXML:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003568 ret = parse_any(ctx, data, kw, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569 break;
3570 case YANG_CASE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003571 ret = parse_case(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003572 break;
3573 case YANG_CHOICE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003574 ret = parse_choice(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003575 break;
3576 case YANG_CONTAINER:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003577 ret = parse_container(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003578 break;
3579 case YANG_LEAF:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003580 ret = parse_leaf(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003581 break;
3582 case YANG_LEAF_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003583 ret = parse_leaflist(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584 break;
3585 case YANG_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003586 ret = parse_list(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003587 break;
3588 case YANG_CUSTOM:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003589 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590 break;
3591 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003592 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003593 return LY_EVALID;
3594 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003595 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003596 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003597 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003598
3599 return ret;
3600}
3601
Michal Vaskoea5abea2018-09-18 13:10:54 +02003602/**
3603 * @brief Parse the container statement.
3604 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003605 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003606 * @param[in,out] data Data to read from, always moved to currently handled character.
3607 * @param[in,out] siblings Siblings to add to.
3608 *
3609 * @return LY_ERR values.
3610 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003611static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003612parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003613{
3614 LY_ERR ret = 0;
3615 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003616 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003617 enum yang_keyword kw;
3618 struct lysp_node *iter;
3619 struct lysp_node_container *cont;
3620
3621 /* create structure */
3622 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003623 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003624 cont->nodetype = LYS_CONTAINER;
3625
3626 /* insert into siblings */
3627 if (!*siblings) {
3628 *siblings = (struct lysp_node *)cont;
3629 } else {
3630 for (iter = *siblings; iter->next; iter = iter->next);
3631 iter->next = (struct lysp_node *)cont;
3632 }
3633
3634 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003635 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003636 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003637
Radek Krejci44ceedc2018-10-02 15:54:31 +02003638 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003639
3640 /* parse substatements */
3641 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003642 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643
3644 switch (kw) {
3645 case YANG_CONFIG:
3646 ret = parse_config(ctx, data, &cont->flags, &cont->exts);
3647 break;
3648 case YANG_DESCRIPTION:
3649 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts);
3650 break;
3651 case YANG_IF_FEATURE:
3652 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts);
3653 break;
3654 case YANG_REFERENCE:
3655 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts);
3656 break;
3657 case YANG_STATUS:
3658 ret = parse_status(ctx, data, &cont->flags, &cont->exts);
3659 break;
3660 case YANG_WHEN:
3661 ret = parse_when(ctx, data, &cont->when);
3662 break;
3663 case YANG_PRESENCE:
3664 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts);
3665 break;
3666
3667 case YANG_ANYDATA:
3668 case YANG_ANYXML:
3669 ret = parse_any(ctx, data, kw, &cont->child);
3670 break;
3671 case YANG_CHOICE:
3672 ret = parse_choice(ctx, data, &cont->child);
3673 break;
3674 case YANG_CONTAINER:
3675 ret = parse_container(ctx, data, &cont->child);
3676 break;
3677 case YANG_LEAF:
3678 ret = parse_leaf(ctx, data, &cont->child);
3679 break;
3680 case YANG_LEAF_LIST:
3681 ret = parse_leaflist(ctx, data, &cont->child);
3682 break;
3683 case YANG_LIST:
3684 ret = parse_list(ctx, data, &cont->child);
3685 break;
3686 case YANG_USES:
3687 ret = parse_uses(ctx, data, &cont->child);
3688 break;
3689
3690 case YANG_TYPEDEF:
3691 ret = parse_typedef(ctx, data, &cont->typedefs);
3692 break;
3693 case YANG_MUST:
3694 ret = parse_restrs(ctx, data, kw, &cont->musts);
3695 break;
3696 case YANG_ACTION:
3697 ret = parse_action(ctx, data, &cont->actions);
3698 break;
3699 case YANG_GROUPING:
3700 ret = parse_grouping(ctx, data, &cont->groupings);
3701 break;
3702 case YANG_NOTIFICATION:
3703 ret = parse_notif(ctx, data, &cont->notifs);
3704 break;
3705 case YANG_CUSTOM:
3706 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts);
3707 break;
3708 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003709 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003710 return LY_EVALID;
3711 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003712 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003713 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003714 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003715
3716 return ret;
3717}
3718
Michal Vaskoea5abea2018-09-18 13:10:54 +02003719/**
3720 * @brief Parse the list statement.
3721 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003722 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003723 * @param[in,out] data Data to read from, always moved to currently handled character.
3724 * @param[in,out] siblings Siblings to add to.
3725 *
3726 * @return LY_ERR values.
3727 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003728static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003729parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003730{
3731 LY_ERR ret = 0;
3732 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003733 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003734 enum yang_keyword kw;
3735 struct lysp_node *iter;
3736 struct lysp_node_list *list;
3737
3738 /* create structure */
3739 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003740 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003741 list->nodetype = LYS_LIST;
3742
3743 /* insert into siblings */
3744 if (!*siblings) {
3745 *siblings = (struct lysp_node *)list;
3746 } else {
3747 for (iter = *siblings; iter->next; iter = iter->next);
3748 iter->next = (struct lysp_node *)list;
3749 }
3750
3751 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003752 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003753 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003754
Radek Krejci44ceedc2018-10-02 15:54:31 +02003755 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003756
3757 /* parse substatements */
3758 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003759 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003760
3761 switch (kw) {
3762 case YANG_CONFIG:
3763 ret = parse_config(ctx, data, &list->flags, &list->exts);
3764 break;
3765 case YANG_DESCRIPTION:
3766 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts);
3767 break;
3768 case YANG_IF_FEATURE:
3769 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts);
3770 break;
3771 case YANG_REFERENCE:
3772 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts);
3773 break;
3774 case YANG_STATUS:
3775 ret = parse_status(ctx, data, &list->flags, &list->exts);
3776 break;
3777 case YANG_WHEN:
3778 ret = parse_when(ctx, data, &list->when);
3779 break;
3780 case YANG_KEY:
3781 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts);
3782 break;
3783 case YANG_MAX_ELEMENTS:
3784 ret = parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts);
3785 break;
3786 case YANG_MIN_ELEMENTS:
3787 ret = parse_minelements(ctx, data, &list->min, &list->flags, &list->exts);
3788 break;
3789 case YANG_ORDERED_BY:
3790 ret = parse_orderedby(ctx, data, &list->flags, &list->exts);
3791 break;
3792 case YANG_UNIQUE:
3793 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts);
3794 break;
3795
3796 case YANG_ANYDATA:
3797 case YANG_ANYXML:
3798 ret = parse_any(ctx, data, kw, &list->child);
3799 break;
3800 case YANG_CHOICE:
3801 ret = parse_choice(ctx, data, &list->child);
3802 break;
3803 case YANG_CONTAINER:
3804 ret = parse_container(ctx, data, &list->child);
3805 break;
3806 case YANG_LEAF:
3807 ret = parse_leaf(ctx, data, &list->child);
3808 break;
3809 case YANG_LEAF_LIST:
3810 ret = parse_leaflist(ctx, data, &list->child);
3811 break;
3812 case YANG_LIST:
3813 ret = parse_list(ctx, data, &list->child);
3814 break;
3815 case YANG_USES:
3816 ret = parse_uses(ctx, data, &list->child);
3817 break;
3818
3819 case YANG_TYPEDEF:
3820 ret = parse_typedef(ctx, data, &list->typedefs);
3821 break;
3822 case YANG_MUST:
3823 ret = parse_restrs(ctx, data, kw, &list->musts);
3824 break;
3825 case YANG_ACTION:
3826 ret = parse_action(ctx, data, &list->actions);
3827 break;
3828 case YANG_GROUPING:
3829 ret = parse_grouping(ctx, data, &list->groupings);
3830 break;
3831 case YANG_NOTIFICATION:
3832 ret = parse_notif(ctx, data, &list->notifs);
3833 break;
3834 case YANG_CUSTOM:
3835 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts);
3836 break;
3837 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003838 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003839 return LY_EVALID;
3840 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003841 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003842 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003843 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003844
3845 return ret;
3846}
3847
Michal Vaskoea5abea2018-09-18 13:10:54 +02003848/**
3849 * @brief Parse the yin-element statement.
3850 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003851 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003852 * @param[in,out] data Data to read from, always moved to currently handled character.
3853 * @param[in,out] flags Flags to write to.
3854 * @param[in,out] exts Extension instances to add to.
3855 *
3856 * @return LY_ERR values.
3857 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003858static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003859parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003860{
3861 LY_ERR ret = 0;
3862 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003863 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003864 enum yang_keyword kw;
3865
3866 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003867 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003868 return LY_EVALID;
3869 }
3870
3871 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003872 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003873 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003874
3875 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3876 *flags |= LYS_YINELEM_TRUE;
3877 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3878 *flags |= LYS_YINELEM_FALSE;
3879 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003880 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003881 free(buf);
3882 return LY_EVALID;
3883 }
3884 free(buf);
3885
3886 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003887 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003888
3889 switch (kw) {
3890 case YANG_CUSTOM:
3891 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02003892 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003893 break;
3894 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003895 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003896 return LY_EVALID;
3897 }
3898 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003899 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003900
3901 return ret;
3902}
3903
Michal Vaskoea5abea2018-09-18 13:10:54 +02003904/**
3905 * @brief Parse the yin-element statement.
3906 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003907 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003908 * @param[in,out] data Data to read from, always moved to currently handled character.
3909 * @param[in,out] argument Value to write to.
3910 * @param[in,out] flags Flags to write to.
3911 * @param[in,out] exts Extension instances to add to.
3912 *
3913 * @return LY_ERR values.
3914 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003915static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003916parse_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 +02003917{
3918 LY_ERR ret = 0;
3919 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003920 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003921 enum yang_keyword kw;
3922
3923 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003924 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003925 return LY_EVALID;
3926 }
3927
3928 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003929 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003930 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003931
Radek Krejci44ceedc2018-10-02 15:54:31 +02003932 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003933 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003934 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003935
3936 switch (kw) {
3937 case YANG_YIN_ELEMENT:
3938 ret = parse_yinelement(ctx, data, flags, exts);
3939 break;
3940 case YANG_CUSTOM:
3941 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts);
3942 break;
3943 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003944 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003945 return LY_EVALID;
3946 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003947 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003948 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003949 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003950
3951 return ret;
3952}
3953
Michal Vaskoea5abea2018-09-18 13:10:54 +02003954/**
3955 * @brief Parse the extension statement.
3956 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003957 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003958 * @param[in,out] data Data to read from, always moved to currently handled character.
3959 * @param[in,out] extensions Extensions to add to.
3960 *
3961 * @return LY_ERR values.
3962 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003963static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003964parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003965{
3966 LY_ERR ret = 0;
3967 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003968 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003969 enum yang_keyword kw;
3970 struct lysp_ext *ex;
3971
3972 LYSP_ARRAY_NEW_RET(ctx, extensions, ex, LY_EMEM);
3973
3974 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003975 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003976 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003977
Radek Krejci44ceedc2018-10-02 15:54:31 +02003978 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003979 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003980 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003981
3982 switch (kw) {
3983 case YANG_DESCRIPTION:
3984 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts);
3985 break;
3986 case YANG_REFERENCE:
3987 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts);
3988 break;
3989 case YANG_STATUS:
3990 ret = parse_status(ctx, data, &ex->flags, &ex->exts);
3991 break;
3992 case YANG_ARGUMENT:
3993 ret = parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts);
3994 break;
3995 case YANG_CUSTOM:
3996 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts);
3997 break;
3998 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003999 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004000 return LY_EVALID;
4001 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004002 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004003 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004004 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004005
4006 return ret;
4007}
4008
Michal Vaskoea5abea2018-09-18 13:10:54 +02004009/**
4010 * @brief Parse the deviate statement.
4011 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004012 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004013 * @param[in,out] data Data to read from, always moved to currently handled character.
4014 * @param[in,out] deviates Deviates to add to.
4015 *
4016 * @return LY_ERR values.
4017 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004018static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004019parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004020{
4021 LY_ERR ret = 0;
4022 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004023 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004024 enum yang_keyword kw;
4025 struct lysp_deviate *iter, *d;
4026 struct lysp_deviate_add *d_add = NULL;
4027 struct lysp_deviate_rpl *d_rpl = NULL;
4028 struct lysp_deviate_del *d_del = NULL;
4029 const char **d_units, ***d_uniques, ***d_dflts;
4030 struct lysp_restr **d_musts;
4031 uint16_t *d_flags;
4032 uint32_t *d_min, *d_max;
4033
4034 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004035 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004036 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004037
4038 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4039 dev_mod = LYS_DEV_NOT_SUPPORTED;
4040 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4041 dev_mod = LYS_DEV_ADD;
4042 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4043 dev_mod = LYS_DEV_REPLACE;
4044 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4045 dev_mod = LYS_DEV_DELETE;
4046 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004047 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004048 free(buf);
4049 return LY_EVALID;
4050 }
4051 free(buf);
4052
4053 /* create structure */
4054 switch (dev_mod) {
4055 case LYS_DEV_NOT_SUPPORTED:
4056 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004057 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004058 break;
4059 case LYS_DEV_ADD:
4060 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004061 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004062 d = (struct lysp_deviate *)d_add;
4063 d_units = &d_add->units;
4064 d_uniques = &d_add->uniques;
4065 d_dflts = &d_add->dflts;
4066 d_musts = &d_add->musts;
4067 d_flags = &d_add->flags;
4068 d_min = &d_add->min;
4069 d_max = &d_add->max;
4070 break;
4071 case LYS_DEV_REPLACE:
4072 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004073 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004074 d = (struct lysp_deviate *)d_rpl;
4075 d_units = &d_rpl->units;
4076 d_flags = &d_rpl->flags;
4077 d_min = &d_rpl->min;
4078 d_max = &d_rpl->max;
4079 break;
4080 case LYS_DEV_DELETE:
4081 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004082 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004083 d = (struct lysp_deviate *)d_del;
4084 d_units = &d_del->units;
4085 d_uniques = &d_del->uniques;
4086 d_dflts = &d_del->dflts;
4087 d_musts = &d_del->musts;
4088 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004089 break;
4090 default:
4091 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004092 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004093 }
4094 d->mod = dev_mod;
4095
4096 /* insert into siblings */
4097 if (!*deviates) {
4098 *deviates = d;
4099 } else {
4100 for (iter = *deviates; iter->next; iter = iter->next);
4101 iter->next = d;
4102 }
4103
4104 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004105 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004106
4107 switch (kw) {
4108 case YANG_CONFIG:
4109 switch (dev_mod) {
4110 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004111 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004112 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004113 return LY_EVALID;
4114 default:
4115 ret = parse_config(ctx, data, d_flags, &d->exts);
4116 break;
4117 }
4118 break;
4119 case YANG_DEFAULT:
4120 switch (dev_mod) {
4121 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004122 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004123 return LY_EVALID;
4124 case LYS_DEV_REPLACE:
4125 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts);
4126 break;
4127 default:
4128 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts);
4129 break;
4130 }
4131 break;
4132 case YANG_MANDATORY:
4133 switch (dev_mod) {
4134 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004135 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004136 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004137 return LY_EVALID;
4138 default:
4139 ret = parse_mandatory(ctx, data, d_flags, &d->exts);
4140 break;
4141 }
4142 break;
4143 case YANG_MAX_ELEMENTS:
4144 switch (dev_mod) {
4145 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004146 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004147 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004148 return LY_EVALID;
4149 default:
4150 ret = parse_maxelements(ctx, data, d_max, d_flags, &d->exts);
4151 break;
4152 }
4153 break;
4154 case YANG_MIN_ELEMENTS:
4155 switch (dev_mod) {
4156 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004157 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004158 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004159 return LY_EVALID;
4160 default:
4161 ret = parse_minelements(ctx, data, d_min, d_flags, &d->exts);
4162 break;
4163 }
4164 break;
4165 case YANG_MUST:
4166 switch (dev_mod) {
4167 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004168 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004169 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004170 return LY_EVALID;
4171 default:
4172 ret = parse_restrs(ctx, data, kw, d_musts);
4173 break;
4174 }
4175 break;
4176 case YANG_TYPE:
4177 switch (dev_mod) {
4178 case LYS_DEV_NOT_SUPPORTED:
4179 case LYS_DEV_ADD:
4180 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004181 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004182 return LY_EVALID;
4183 default:
4184 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004185 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004186 ret = parse_type(ctx, data, d_rpl->type);
4187 break;
4188 }
4189 break;
4190 case YANG_UNIQUE:
4191 switch (dev_mod) {
4192 case LYS_DEV_NOT_SUPPORTED:
4193 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004194 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004195 return LY_EVALID;
4196 default:
4197 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts);
4198 break;
4199 }
4200 break;
4201 case YANG_UNITS:
4202 switch (dev_mod) {
4203 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004204 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004205 return LY_EVALID;
4206 default:
4207 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts);
4208 break;
4209 }
4210 break;
4211 case YANG_CUSTOM:
4212 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts);
4213 break;
4214 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004215 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004216 return LY_EVALID;
4217 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004218 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004219 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004220 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004221
4222 return ret;
4223}
4224
Michal Vaskoea5abea2018-09-18 13:10:54 +02004225/**
4226 * @brief Parse the deviation statement.
4227 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004228 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004229 * @param[in,out] data Data to read from, always moved to currently handled character.
4230 * @param[in,out] deviations Deviations to add to.
4231 *
4232 * @return LY_ERR values.
4233 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004234static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004235parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004236{
4237 LY_ERR ret = 0;
4238 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004239 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004240 enum yang_keyword kw;
4241 struct lysp_deviation *dev;
4242
4243 LYSP_ARRAY_NEW_RET(ctx, deviations, dev, LY_EMEM);
4244
4245 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004246 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004247 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004248
Radek Krejci44ceedc2018-10-02 15:54:31 +02004249 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004250 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004251 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004252
4253 switch (kw) {
4254 case YANG_DESCRIPTION:
4255 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts);
4256 break;
4257 case YANG_DEVIATE:
4258 ret = parse_deviate(ctx, data, &dev->deviates);
4259 break;
4260 case YANG_REFERENCE:
4261 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts);
4262 break;
4263 case YANG_CUSTOM:
4264 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts);
4265 break;
4266 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004267 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004268 return LY_EVALID;
4269 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004270 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004271 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004272 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004273
4274 /* mandatory substatements */
4275 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004276 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004277 return LY_EVALID;
4278 }
4279
4280 return ret;
4281}
4282
Michal Vaskoea5abea2018-09-18 13:10:54 +02004283/**
4284 * @brief Parse the feature statement.
4285 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004286 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004287 * @param[in,out] data Data to read from, always moved to currently handled character.
4288 * @param[in,out] features Features to add to.
4289 *
4290 * @return LY_ERR values.
4291 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004292static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004293parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004294{
4295 LY_ERR ret = 0;
4296 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004297 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004298 enum yang_keyword kw;
4299 struct lysp_feature *feat;
4300
4301 LYSP_ARRAY_NEW_RET(ctx, features, feat, LY_EMEM);
4302
4303 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004304 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004305 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004306
Radek Krejci44ceedc2018-10-02 15:54:31 +02004307 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004308 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004309 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004310
4311 switch (kw) {
4312 case YANG_DESCRIPTION:
4313 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts);
4314 break;
4315 case YANG_IF_FEATURE:
4316 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts);
4317 break;
4318 case YANG_REFERENCE:
4319 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts);
4320 break;
4321 case YANG_STATUS:
4322 ret = parse_status(ctx, data, &feat->flags, &feat->exts);
4323 break;
4324 case YANG_CUSTOM:
4325 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts);
4326 break;
4327 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004328 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004329 return LY_EMEM;
4330 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004331 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004332 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004333 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004334
4335 return ret;
4336}
4337
Michal Vaskoea5abea2018-09-18 13:10:54 +02004338/**
4339 * @brief Parse the identity statement.
4340 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004341 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004342 * @param[in,out] data Data to read from, always moved to currently handled character.
4343 * @param[in,out] identities Identities to add to.
4344 *
4345 * @return LY_ERR values.
4346 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004347static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004348parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004349{
4350 LY_ERR ret = 0;
4351 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004352 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004353 enum yang_keyword kw;
4354 struct lysp_ident *ident;
4355
4356 LYSP_ARRAY_NEW_RET(ctx, identities, ident, LY_EMEM);
4357
4358 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004359 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004360 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004361
Radek Krejci44ceedc2018-10-02 15:54:31 +02004362 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004363 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004364 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004365
4366 switch (kw) {
4367 case YANG_DESCRIPTION:
4368 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts);
4369 break;
4370 case YANG_IF_FEATURE:
4371 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts);
4372 break;
4373 case YANG_REFERENCE:
4374 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts);
4375 break;
4376 case YANG_STATUS:
4377 ret = parse_status(ctx, data, &ident->flags, &ident->exts);
4378 break;
4379 case YANG_BASE:
4380 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts);
4381 break;
4382 case YANG_CUSTOM:
4383 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts);
4384 break;
4385 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004386 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004387 return LY_EVALID;
4388 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004389 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004390 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004391 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004392
4393 return ret;
4394}
4395
Michal Vaskoea5abea2018-09-18 13:10:54 +02004396/**
4397 * @brief Parse the module or submodule statement.
4398 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004399 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004400 * @param[in,out] data Data to read from, always moved to currently handled character.
4401 * @param[in,out] mod Module to write to.
4402 *
4403 * @return LY_ERR values.
4404 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004405static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004406parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004407{
4408 LY_ERR ret = 0;
4409 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004410 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004411 enum yang_keyword kw, prev_kw = 0;
4412 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4413
4414 /* (sub)module name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004415 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004416 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004417
Radek Krejci44ceedc2018-10-02 15:54:31 +02004418 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004419 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004420 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004421
4422 switch (kw) {
4423 /* module header */
4424 case YANG_NAMESPACE:
4425 case YANG_PREFIX:
4426 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004427 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004428 return LY_EVALID;
4429 }
4430 /* fallthrough */
4431 case YANG_BELONGS_TO:
4432 if ((kw == YANG_BELONGS_TO) && !mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004433 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004434 return LY_EVALID;
4435 }
4436 /* fallthrough */
4437 case YANG_YANG_VERSION:
4438 if (mod_stmt > Y_MOD_MODULE_HEADER) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004439 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004440 return LY_EVALID;
4441 }
4442 break;
4443 /* linkage */
4444 case YANG_INCLUDE:
4445 case YANG_IMPORT:
4446 if (mod_stmt > Y_MOD_LINKAGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004447 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004448 return LY_EVALID;
4449 }
4450 mod_stmt = Y_MOD_LINKAGE;
4451 break;
4452 /* meta */
4453 case YANG_ORGANIZATION:
4454 case YANG_CONTACT:
4455 case YANG_DESCRIPTION:
4456 case YANG_REFERENCE:
4457 if (mod_stmt > Y_MOD_META) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004458 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004459 return LY_EVALID;
4460 }
4461 mod_stmt = Y_MOD_META;
4462 break;
4463
4464 /* revision */
4465 case YANG_REVISION:
4466 if (mod_stmt > Y_MOD_REVISION) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004467 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004468 return LY_EVALID;
4469 }
4470 mod_stmt = Y_MOD_REVISION;
4471 break;
4472
4473 /* body */
4474 case YANG_ANYDATA:
4475 case YANG_ANYXML:
4476 case YANG_AUGMENT:
4477 case YANG_CHOICE:
4478 case YANG_CONTAINER:
4479 case YANG_DEVIATION:
4480 case YANG_EXTENSION:
4481 case YANG_FEATURE:
4482 case YANG_GROUPING:
4483 case YANG_IDENTITY:
4484 case YANG_LEAF:
4485 case YANG_LEAF_LIST:
4486 case YANG_LIST:
4487 case YANG_NOTIFICATION:
4488 case YANG_RPC:
4489 case YANG_TYPEDEF:
4490 case YANG_USES:
4491 case YANG_CUSTOM:
4492 mod_stmt = Y_MOD_BODY;
4493 break;
4494 default:
4495 /* error handled in the next switch */
4496 break;
4497 }
4498 prev_kw = kw;
4499
4500 switch (kw) {
4501 /* module header */
4502 case YANG_YANG_VERSION:
4503 ret = parse_yangversion(ctx, data, mod);
4504 break;
4505 case YANG_NAMESPACE:
4506 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->ns, Y_STR_ARG, &mod->exts);
4507 break;
4508 case YANG_PREFIX:
4509 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts);
4510 break;
4511 case YANG_BELONGS_TO:
4512 ret = parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts);
4513 break;
4514
4515 /* linkage */
4516 case YANG_INCLUDE:
4517 ret = parse_include(ctx, data, &mod->includes);
4518 break;
4519 case YANG_IMPORT:
4520 ret = parse_import(ctx, data, &mod->imports);
4521 break;
4522
4523 /* meta */
4524 case YANG_ORGANIZATION:
4525 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->org, Y_STR_ARG, &mod->exts);
4526 break;
4527 case YANG_CONTACT:
4528 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->contact, Y_STR_ARG, &mod->exts);
4529 break;
4530 case YANG_DESCRIPTION:
4531 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->dsc, Y_STR_ARG, &mod->exts);
4532 break;
4533 case YANG_REFERENCE:
4534 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->ref, Y_STR_ARG, &mod->exts);
4535 break;
4536
4537 /* revision */
4538 case YANG_REVISION:
4539 ret = parse_revision(ctx, data, &mod->revs);
4540 break;
4541
4542 /* body */
4543 case YANG_ANYDATA:
4544 case YANG_ANYXML:
4545 ret = parse_any(ctx, data, kw, &mod->data);
4546 break;
4547 case YANG_CHOICE:
4548 ret = parse_choice(ctx, data, &mod->data);
4549 break;
4550 case YANG_CONTAINER:
4551 ret = parse_container(ctx, data, &mod->data);
4552 break;
4553 case YANG_LEAF:
4554 ret = parse_leaf(ctx, data, &mod->data);
4555 break;
4556 case YANG_LEAF_LIST:
4557 ret = parse_leaflist(ctx, data, &mod->data);
4558 break;
4559 case YANG_LIST:
4560 ret = parse_list(ctx, data, &mod->data);
4561 break;
4562 case YANG_USES:
4563 ret = parse_uses(ctx, data, &mod->data);
4564 break;
4565
4566 case YANG_AUGMENT:
4567 ret = parse_augment(ctx, data, &mod->augments);
4568 break;
4569 case YANG_DEVIATION:
4570 ret = parse_deviation(ctx, data, &mod->deviations);
4571 break;
4572 case YANG_EXTENSION:
4573 ret = parse_extension(ctx, data, &mod->extensions);
4574 break;
4575 case YANG_FEATURE:
4576 ret = parse_feature(ctx, data, &mod->features);
4577 break;
4578 case YANG_GROUPING:
4579 ret = parse_grouping(ctx, data, &mod->groupings);
4580 break;
4581 case YANG_IDENTITY:
4582 ret = parse_identity(ctx, data, &mod->identities);
4583 break;
4584 case YANG_NOTIFICATION:
4585 ret = parse_notif(ctx, data, &mod->notifs);
4586 break;
4587 case YANG_RPC:
4588 ret = parse_action(ctx, data, &mod->rpcs);
4589 break;
4590 case YANG_TYPEDEF:
4591 ret = parse_typedef(ctx, data, &mod->typedefs);
4592 break;
4593 case YANG_CUSTOM:
4594 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts);
4595 break;
4596
4597 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004598 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004599 return LY_EVALID;
4600 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004601 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004602 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004603 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004604
4605 /* mandatory substatements */
4606 if (mod->submodule) {
4607 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004608 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004609 return LY_EVALID;
4610 }
4611 } else {
4612 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004613 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004614 return LY_EVALID;
4615 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004616 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004617 return LY_EVALID;
4618 }
4619 }
4620
4621 return ret;
4622}
4623
Radek Krejcid4557c62018-09-17 11:42:09 +02004624LY_ERR
Michal Vasko7fbc8162018-09-17 10:35:16 +02004625yang_parse(struct ly_ctx *ctx, const char *data, struct lysp_module **mod_p)
4626{
4627 LY_ERR ret = 0;
4628 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004629 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004630 enum yang_keyword kw;
4631 struct lysp_module *mod;
Radek Krejci44ceedc2018-10-02 15:54:31 +02004632 struct ly_parser_ctx context;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004633
Radek Krejci44ceedc2018-10-02 15:54:31 +02004634 context.ctx = ctx;
4635 context.line = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004636
4637 /* "module"/"submodule" */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004638 ret = get_keyword(&context, &data, &kw, &word, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004639 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004640
4641 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004642 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004643 ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004644 goto error;
4645 }
4646
4647 mod = calloc(1, sizeof *mod);
4648 LY_CHECK_ERR_GOTO(!mod, LOGMEM(ctx), error);
4649 if (kw == YANG_SUBMODULE) {
4650 mod->submodule = 1;
4651 }
Radek Krejci9fcacc12018-10-11 15:59:11 +02004652 mod->ctx = ctx;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004653
4654 /* substatements */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004655 ret = parse_sub_module(&context, &data, mod);
Radek Krejcic59bc972018-09-17 16:13:06 +02004656 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004657
4658 /* read some trailing spaces or new lines */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004659 ret = get_argument(&context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004660 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004661
4662 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004663 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004664 word_len, word);
4665 free(buf);
4666 goto error;
4667 }
4668 assert(!buf);
4669
4670 *mod_p = mod;
4671 return ret;
4672
4673error:
Radek Krejci9fcacc12018-10-11 15:59:11 +02004674 lysp_module_free(mod);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004675 return ret;
4676}