blob: 77c7084988f716bf2c7fc048f4eb38fd80f61ff3 [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
54#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);} \
55 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
56
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020057#define MOVE_INPUT(CTX, DATA, COUNT) (*(data))+=COUNT;(CTX)->indent+=COUNT
58
Radek Krejci44ceedc2018-10-02 15:54:31 +020059#define LOGVAL_YANG(CTX, ...) LOGVAL((CTX)->ctx, LY_VLOG_LINE, &(CTX)->line, __VA_ARGS__)
60
Michal Vaskoea5abea2018-09-18 13:10:54 +020061/**
62 * @brief Loop through all substatements providing, return if there are none.
63 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020064 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020065 * @param[in] DATA Raw data to read from.
66 * @param[out] KW YANG keyword read.
67 * @param[out] WORD Pointer to the keyword itself.
68 * @param[out] WORD_LEN Length of the keyword.
69 * @param[out] ERR Variable for error storing.
70 *
71 * @return In case there are no substatements or a fatal error encountered.
72 */
Michal Vasko7fbc8162018-09-17 10:35:16 +020073#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR) \
74 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
Radek Krejcic59bc972018-09-17 16:13:06 +020075 LY_CHECK_RET(ERR); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020076 \
77 if (KW == YANG_SEMICOLON) { \
78 return ERR; \
79 } \
80 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +020081 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020082 return LY_EVALID; \
83 } \
84 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
85 !ERR && (KW != YANG_RIGHT_BRACE); \
86 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
87
Radek Krejci44ceedc2018-10-02 15:54:31 +020088static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
89static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
90static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
91static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
92static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
93static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +020094
Michal Vaskoea5abea2018-09-18 13:10:54 +020095/**
96 * @brief Add another character to dynamic buffer, a low-level function.
97 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020098 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +020099 *
Radek Krejci404251e2018-10-09 12:06:44 +0200100 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200101 * @param[in, out] input Input string to process.
102 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200103 * @param[in,out] buf Buffer to use, can be moved by realloc().
104 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200105 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200106 *
107 * @return LY_ERR values.
108 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200109static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200110buf_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 +0200111{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200112 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200113 *buf_len += 16;
114 *buf = ly_realloc(*buf, *buf_len);
115 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
116 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200117 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200118
Radek Krejci44ceedc2018-10-02 15:54:31 +0200119 (*buf_used) += len;
120 (*input) += len;
121
Michal Vasko7fbc8162018-09-17 10:35:16 +0200122 return LY_SUCCESS;
123}
124
Michal Vaskoea5abea2018-09-18 13:10:54 +0200125/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200126 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200127 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200128 * @param[in] ctx yang parser context for logging.
129 * @param[in] c UTF8 code point of a character to check.
130 * @return LY_ERR values.
131 */
132static LY_ERR
133check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
134{
135 if (!is_yangutf8char(c)) {
136 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
137 return LY_EVALID;
138 }
139 return LY_SUCCESS;
140}
141
142/**
143 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
144 *
145 * @param[in] ctx yang parser context for logging.
146 * @param[in] c UTF8 code point of a character to check.
147 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200148 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
149 * 0 - colon not yet found (no prefix)
150 * 1 - \p c is the colon character
151 * 2 - prefix already processed, now processing the identifier
152 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200153 * If the identifier cannot be prefixed, NULL is expected.
154 * @return LY_ERR values.
155 */
156static LY_ERR
157check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
158{
159 if (first || (prefix && (*prefix) == 1)) {
160 if (!is_yangidentstartchar(c)) {
161 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
162 return LY_EVALID;
163 }
164 if (first) {
165 (*prefix) = 0;
166 } else {
167 (*prefix) = 2;
168 }
169 } else if (c == ':' && prefix && (*prefix) == 0) {
170 (*prefix) = 1;
171 } else if (!is_yangidentchar(c)) {
172 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
173 return LY_EVALID;
174 }
175
176 return LY_SUCCESS;
177}
178
179/**
180 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
181 *
182 * @param[in] ctx yang parser context for logging.
183 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
184 * when function returns.
185 * @param[in] arg Type of the input string to select method of checking character validity.
186 * @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 +0200187 * 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 +0200188 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
189 * @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 +0200190 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200191 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200192 *
193 * @return LY_ERR values.
194 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200195static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200196buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
197 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200198{
Radek Krejci404251e2018-10-09 12:06:44 +0200199 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200200 unsigned int c;
201 size_t len;
202
203 /* get UTF8 code point (and number of bytes coding the character) */
204 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
205 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
206 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200207 if (c == '\n') {
208 ctx->indent = 0;
209 } else {
210 /* note - even the multibyte character is count as 1 */
211 ++ctx->indent;
212 }
213
Radek Krejci44ceedc2018-10-02 15:54:31 +0200214 /* check character validity */
215 switch (arg) {
216 case Y_IDENTIF_ARG:
217 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
218 break;
219 case Y_PREF_IDENTIF_ARG:
220 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
221 break;
222 case Y_STR_ARG:
223 case Y_MAYBE_STR_ARG:
224 LY_CHECK_RET(check_stringchar(ctx, c));
225 break;
226 }
227
Michal Vasko7fbc8162018-09-17 10:35:16 +0200228 if (word_b && *word_b) {
229 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200230 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200231 return LY_EMEM;
232 }
233
234 /* in case of realloc */
235 *word_p = *word_b;
236 } else if (need_buf) {
237 /* first time we need a buffer, copy everything read up to now */
238 if (*word_len) {
239 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200240 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200241 *buf_len = *word_len;
242 memcpy(*word_b, *word_p, *word_len);
243 }
244
245 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200246 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200247 return LY_EMEM;
248 }
249
250 /* in case of realloc */
251 *word_p = *word_b;
252 } else {
253 /* just remember the first character pointer */
254 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200255 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200256 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200257 /* ... and update the word's length */
258 (*word_len) += len;
259 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200260 }
261
262 return LY_SUCCESS;
263}
264
Michal Vaskoea5abea2018-09-18 13:10:54 +0200265/**
266 * @brief Skip YANG comment in data.
267 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200268 * @param[in] ctx yang parser context for logging.
269 * @param[in,out] data Data to read from, automatically moved after the comment.
270 * @param[in] comment Type of the comment to process:
271 * 1 for a one-line comment,
272 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200273 *
274 * @return LY_ERR values.
275 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200276static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200277skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200278{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200279 /* internal statuses: 0 - comment ended,
280 * 1 - in line comment,
281 * 2 - in block comment,
282 * 3 - in block comment with last read character '*'
283 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200284 while (**data && comment) {
285 switch (comment) {
286 case 1:
287 if (**data == '\n') {
288 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200289 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200290 }
291 break;
292 case 2:
293 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200294 comment = 3;
295 } else if (**data == '\n') {
296 ++ctx->line;
297 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200298 break;
299 case 3:
300 if (**data == '/') {
301 comment = 0;
302 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200303 if (**data == '\n') {
304 ++ctx->line;
305 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200306 comment = 2;
307 }
308 break;
309 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200310 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200311 }
312
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200313 if (**data == '\n') {
314 ctx->indent = 0;
315 } else {
316 ++ctx->indent;
317 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200318 ++(*data);
319 }
320
321 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200322 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200323 return LY_EVALID;
324 }
325
326 return LY_SUCCESS;
327}
328
Michal Vaskoea5abea2018-09-18 13:10:54 +0200329/**
330 * @brief Read a quoted string from data.
331 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200332 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200333 * @param[in,out] data Data to read from, always moved to currently handled character.
334 * @param[in] arg Type of YANG keyword argument expected.
335 * @param[out] word_p Pointer to the read quoted string.
336 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
337 * set to NULL. Otherwise equal to \p word_p.
338 * @param[out] word_len Length of the read quoted string.
339 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
340 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
341 * indenation in the final quoted string.
342 *
343 * @return LY_ERR values.
344 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200345static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200346read_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 +0200347 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200348{
349 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
350 * 4 - string finished, now skipping whitespaces looking for +,
351 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200352 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200353 const char *c;
354
355 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200356 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200357 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200358 } else {
359 assert(**data == '\'');
360 string = 1;
361 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200362 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200363
364 while (**data && string) {
365 switch (string) {
366 case 1:
367 switch (**data) {
368 case '\'':
369 /* string may be finished, but check for + */
370 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200371 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200372 break;
373 default:
374 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200375 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 +0200376 break;
377 }
378 break;
379 case 2:
380 switch (**data) {
381 case '\"':
382 /* string may be finished, but check for + */
383 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200384 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200385 break;
386 case '\\':
387 /* special character following */
388 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200389 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200390 break;
391 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200392 if (current_indent < block_indent) {
393 ++current_indent;
394 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200395 } else {
396 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200397 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 +0200398 }
399 break;
400 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200401 if (current_indent < block_indent) {
402 assert(need_buf);
403 current_indent += 8;
404 ctx->indent += 8;
405 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
406 /* store leftover spaces from the tab */
407 c = " ";
408 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 +0200409 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200410 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200411 } else {
412 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200413 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 +0200414 /* additional characters for indentation - only 1 was count in buf_store_char */
415 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200416 }
417 break;
418 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200419 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200420 /* we will be removing the indents so we need our own buffer */
421 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200422
423 /* remove trailing tabs and spaces */
424 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
425 --(*word_len);
426 }
427
428 /* start indentation */
429 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200430 }
431
432 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200433 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
434
435 /* maintain line number */
436 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200437
438 /* reset context indentation counter for possible string after this one */
439 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200440 break;
441 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200442 /* first non-whitespace character, stop eating indentation */
443 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200444
445 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200446 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 +0200447 break;
448 }
449 break;
450 case 3:
451 /* string encoded characters */
452 switch (**data) {
453 case 'n':
454 c = "\n";
455 break;
456 case 't':
457 c = "\t";
458 break;
459 case '\"':
460 c = *data;
461 break;
462 case '\\':
463 c = *data;
464 break;
465 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200466 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200467 return LY_EVALID;
468 }
469
470 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200471 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 +0200472
473 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200474 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200475 break;
476 case 4:
477 switch (**data) {
478 case '+':
479 /* string continues */
480 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200481 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200482 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200483 case '\n':
484 ++ctx->line;
485 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200486 case ' ':
487 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200488 /* just skip */
489 break;
490 default:
491 /* string is finished */
492 goto string_end;
493 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200494 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200495 break;
496 case 5:
497 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200498 case '\n':
499 ++ctx->line;
500 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200501 case ' ':
502 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200503 /* skip */
504 break;
505 case '\'':
506 string = 1;
507 break;
508 case '\"':
509 string = 2;
510 break;
511 default:
512 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200513 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200514 return LY_EVALID;
515 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200516 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200517 break;
518 default:
519 return LY_EINT;
520 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200521 }
522
523string_end:
524 return LY_SUCCESS;
525}
526
Michal Vaskoea5abea2018-09-18 13:10:54 +0200527/**
528 * @brief Get another YANG string from the raw data.
529 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200530 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200531 * @param[in,out] data Data to read from, always moved to currently handled character.
532 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200533 * @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 +0200534 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
535 * set to NULL. Otherwise equal to \p word_p.
536 * @param[out] word_len Length of the read string.
537 *
538 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200539 */
540static LY_ERR
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200541get_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 +0200542{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200543 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200544 LY_ERR ret;
545
546 /* word buffer - dynamically allocated */
547 *word_b = NULL;
548
549 /* word pointer - just a pointer to data */
550 *word_p = NULL;
551
552 *word_len = 0;
553 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200554 switch (**data) {
555 case '\'':
556 case '\"':
557 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200558 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
559 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
560 "unquoted string character, optsep, semicolon or opening brace");
561 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200562 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200563 ret = read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200564 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200565 goto str_end;
566 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200567 if ((*data)[1] == '/') {
568 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200569 MOVE_INPUT(ctx, data, 2);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200570 ret = skip_comment(ctx, data, 1);
571 } else if ((*data)[1] == '*') {
572 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200573 MOVE_INPUT(ctx, data, 2);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200574 ret = skip_comment(ctx, data, 2);
575 } else {
576 /* not a comment after all */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200577 ret = buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0);
578 }
579 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200580 break;
581 case ' ':
582 if (*word_len) {
583 /* word is finished */
584 goto str_end;
585 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200586 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200587 break;
588 case '\t':
589 if (*word_len) {
590 /* word is finished */
591 goto str_end;
592 }
593 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200594 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200595
596 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200597 break;
598 case '\n':
599 if (*word_len) {
600 /* word is finished */
601 goto str_end;
602 }
603 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200604 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200605
606 /* track line numbers */
607 ++ctx->line;
608
609 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200610 break;
611 case ';':
612 case '{':
613 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
614 /* word is finished */
615 goto str_end;
616 }
617
Radek Krejci44ceedc2018-10-02 15:54:31 +0200618 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200619 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200620 case '}':
621 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
622 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
623 "unquoted string character, optsep, semicolon or opening brace");
624 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200625 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200626 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 +0200627 break;
628 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200629 }
630
631str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200632 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200633 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200634 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
635 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
636 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200637 *word_p = *word_b;
638 }
639
640 return LY_SUCCESS;
641}
642
Michal Vaskoea5abea2018-09-18 13:10:54 +0200643/**
644 * @brief Get another YANG keyword from the raw data.
645 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200646 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200647 * @param[in,out] data Data to read from, always moved to currently handled character.
648 * @param[out] kw YANG keyword read.
649 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
650 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
651 *
652 * @return LY_ERR values.
653 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200654static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200655get_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 +0200656{
657 LY_ERR ret;
658 int prefix;
659 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200660 unsigned int c;
661 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200662
663 if (word_p) {
664 *word_p = NULL;
665 *word_len = 0;
666 }
667
668 /* first skip "optsep", comments */
669 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200670 switch (**data) {
671 case '/':
672 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200673 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200674 MOVE_INPUT(ctx, data, 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200675 ret = skip_comment(ctx, data, 1);
676 if (ret) {
677 return ret;
678 }
Radek Krejcidcc7b322018-10-11 14:24:02 +0200679 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200680 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200681 MOVE_INPUT(ctx, data, 2);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200682 ret = skip_comment(ctx, data, 2);
683 if (ret) {
684 return ret;
685 }
686 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200687 /* error - not a comment after all, keyword cannot start with slash */
688 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
689 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200690 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200691 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200692 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200693 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200694 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200695 ctx->indent = 0;
696 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200697 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200698 /* skip whitespaces (optsep) */
699 ++ctx->indent;
700 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200701 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200702 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200703 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200704 break;
705 default:
706 /* either a keyword start or an invalid character */
707 goto keyword_start;
708 }
709
710 ++(*data);
711 }
712
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200713#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
714#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
715#define IF_KW_PREFIX_END }
716
Michal Vasko7fbc8162018-09-17 10:35:16 +0200717keyword_start:
718 word_start = *data;
719 *kw = YANG_NONE;
720
721 /* read the keyword itself */
722 switch (**data) {
723 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200724 MOVE_INPUT(ctx, data, 1);
725 IF_KW("rgument", 7, YANG_ARGUMENT)
726 else IF_KW("ugment", 6, YANG_AUGMENT)
727 else IF_KW("ction", 5, YANG_ACTION)
728 else IF_KW_PREFIX("ny", 2)
729 IF_KW("data", 4, YANG_ANYDATA)
730 else IF_KW("xml", 3, YANG_ANYXML)
731 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200732 break;
733 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200734 MOVE_INPUT(ctx, data, 1);
735 IF_KW("ase", 3, YANG_BASE)
736 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
737 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200738 break;
739 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200740 MOVE_INPUT(ctx, data, 1);
741 IF_KW("ase", 3, YANG_CASE)
742 else IF_KW("hoice", 5, YANG_CHOICE)
743 else IF_KW_PREFIX("on", 2)
744 IF_KW("fig", 3, YANG_CONFIG)
745 else IF_KW_PREFIX("ta", 2)
746 IF_KW("ct", 2, YANG_CONTACT)
747 else IF_KW("iner", 4, YANG_CONTAINER)
748 IF_KW_PREFIX_END
749 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200750 break;
751 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200752 MOVE_INPUT(ctx, data, 1);
753 IF_KW_PREFIX("e", 1)
754 IF_KW("fault", 5, YANG_DEFAULT)
755 else IF_KW("scription", 9, YANG_DESCRIPTION)
756 else IF_KW_PREFIX("viat", 4)
757 IF_KW("e", 1, YANG_DEVIATE)
758 else IF_KW("ion", 3, YANG_DEVIATION)
759 IF_KW_PREFIX_END
760 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200761 break;
762 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200763 MOVE_INPUT(ctx, data, 1);
764 IF_KW("num", 3, YANG_ENUM)
765 else IF_KW_PREFIX("rror-", 5)
766 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
767 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
768 IF_KW_PREFIX_END
769 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200770 break;
771 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200772 MOVE_INPUT(ctx, data, 1);
773 IF_KW("eature", 6, YANG_FEATURE)
774 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200775 break;
776 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200777 MOVE_INPUT(ctx, data, 1);
778 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200779 break;
780 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200781 MOVE_INPUT(ctx, data, 1);
782 IF_KW("dentity", 7, YANG_IDENTITY)
783 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
784 else IF_KW("mport", 5, YANG_IMPORT)
785 else IF_KW_PREFIX("n", 1)
786 IF_KW("clude", 5, YANG_INCLUDE)
787 else IF_KW("put", 3, YANG_INPUT)
788 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200789 break;
790 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200791 MOVE_INPUT(ctx, data, 1);
792 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200793 break;
794 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200795 MOVE_INPUT(ctx, data, 1);
796 IF_KW_PREFIX("e", 1)
797 IF_KW("af-list", 7, YANG_LEAF_LIST)
798 else IF_KW("af", 2, YANG_LEAF)
799 else IF_KW("ngth", 4, YANG_LENGTH)
800 IF_KW_PREFIX_END
801 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200802 break;
803 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200804 MOVE_INPUT(ctx, data, 1);
805 IF_KW_PREFIX("a", 1)
806 IF_KW("ndatory", 7, YANG_MANDATORY)
807 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
808 IF_KW_PREFIX_END
809 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
810 else IF_KW("ust", 3, YANG_MUST)
811 else IF_KW_PREFIX("od", 2)
812 IF_KW("ule", 3, YANG_MODULE)
813 else IF_KW("ifier", 5, YANG_MODIFIER)
814 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200815 break;
816 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200817 MOVE_INPUT(ctx, data, 1);
818 IF_KW("amespace", 8, YANG_NAMESPACE)
819 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200820 break;
821 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200822 MOVE_INPUT(ctx, data, 1);
823 IF_KW_PREFIX("r", 1)
824 IF_KW("dered-by", 8, YANG_ORDERED_BY)
825 else IF_KW("ganization", 10, YANG_ORGANIZATION)
826 IF_KW_PREFIX_END
827 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200828 break;
829 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200830 MOVE_INPUT(ctx, data, 1);
831 IF_KW("ath", 3, YANG_PATH)
832 else IF_KW("attern", 6, YANG_PATTERN)
833 else IF_KW("osition", 7, YANG_POSITION)
834 else IF_KW_PREFIX("re", 2)
835 IF_KW("fix", 3, YANG_PREFIX)
836 else IF_KW("sence", 5, YANG_PRESENCE)
837 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200838 break;
839 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200840 MOVE_INPUT(ctx, data, 1);
841 IF_KW("ange", 4, YANG_RANGE)
842 else IF_KW_PREFIX("e", 1)
843 IF_KW_PREFIX("f", 1)
844 IF_KW("erence", 6, YANG_REFERENCE)
845 else IF_KW("ine", 3, YANG_REFINE)
846 IF_KW_PREFIX_END
847 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
848 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
849 else IF_KW("vision", 6, YANG_REVISION)
850 IF_KW_PREFIX_END
851 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200852 break;
853 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200854 MOVE_INPUT(ctx, data, 1);
855 IF_KW("tatus", 5, YANG_STATUS)
856 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200857 break;
858 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200859 MOVE_INPUT(ctx, data, 1);
860 IF_KW("ypedef", 6, YANG_TYPEDEF)
861 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200862 break;
863 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200864 MOVE_INPUT(ctx, data, 1);
865 IF_KW_PREFIX("ni", 2)
866 IF_KW("que", 3, YANG_UNIQUE)
867 else IF_KW("ts", 2, YANG_UNITS)
868 IF_KW_PREFIX_END
869 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200870 break;
871 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200872 MOVE_INPUT(ctx, data, 1);
873 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200874 break;
875 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200876 MOVE_INPUT(ctx, data, 1);
877 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200878 break;
879 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200880 MOVE_INPUT(ctx, data, 1);
881 IF_KW("ang-version", 11, YANG_YANG_VERSION)
882 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200883 break;
884 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200885 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200886 *kw = YANG_SEMICOLON;
887 break;
888 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200889 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200890 *kw = YANG_LEFT_BRACE;
891 break;
892 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200893 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200894 *kw = YANG_RIGHT_BRACE;
895 break;
896 default:
897 break;
898 }
899
900 if (*kw != YANG_NONE) {
901 /* make sure we have the whole keyword */
902 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200903 case '\n':
904 ++ctx->line;
905 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200906 case ' ':
907 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200908 /* mandatory "sep" */
909 break;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200910 case '{':
911 /* allowed only for input and output statements which can be without arguments */
912 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
913 break;
914 }
915 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200916 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200917 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200918 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
919 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200920 return LY_EVALID;
921 }
922 } else {
923 /* still can be an extension */
924 prefix = 0;
925 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200926 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
927 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200928 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200929 /* check character validity */
930 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200931 }
932 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200933 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200934 return LY_EVALID;
935 }
936
937 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200938 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200939 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200940 return LY_EVALID;
941 }
942
943 *kw = YANG_CUSTOM;
944 }
945
946 if (word_p) {
947 *word_p = (char *)word_start;
948 *word_len = *data - word_start;
949 }
950
951 return LY_SUCCESS;
952}
953
Michal Vaskoea5abea2018-09-18 13:10:54 +0200954/**
955 * @brief Parse extension instance substatements.
956 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200957 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200958 * @param[in,out] data Data to read from, always moved to currently handled character.
959 * @param[in] word Extension instance substatement name (keyword).
960 * @param[in] word_len Extension instance substatement name length.
961 * @param[in,out] child Children of this extension instance to add to.
962 *
963 * @return LY_ERR values.
964 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200965static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200966parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200967 struct lysp_stmt **child)
968{
969 char *buf;
970 LY_ERR ret = 0;
971 enum yang_keyword kw;
972 struct lysp_stmt *stmt, *par_child;
973
974 stmt = calloc(1, sizeof *stmt);
975 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
976
Radek Krejci44ceedc2018-10-02 15:54:31 +0200977 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200978
979 /* get optional argument */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200980 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +0200981 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200982
Radek Krejci0ae092d2018-09-20 16:43:19 +0200983 if (word) {
984 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200985 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200986 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200987 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200988 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200989 }
990
991 /* insert into parent statements */
992 if (!*child) {
993 *child = stmt;
994 } else {
995 for (par_child = *child; par_child->next; par_child = par_child->next);
996 par_child->next = stmt;
997 }
998
999 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001000 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001001
1002 ret = parse_ext_substmt(ctx, data, word, word_len, &stmt->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001003 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001004 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001005 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001006
1007 return ret;
1008}
1009
Michal Vaskoea5abea2018-09-18 13:10:54 +02001010/**
1011 * @brief Parse extension instance.
1012 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001013 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001014 * @param[in,out] data Data to read from, always moved to currently handled character.
1015 * @param[in] ext_name Extension instance substatement name (keyword).
1016 * @param[in] ext_name_len Extension instance substatement name length.
1017 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1018 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1019 * @param[in,out] exts Extension instances to add to.
1020 *
1021 * @return LY_ERR values.
1022 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001023static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001024parse_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 +02001025 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1026{
1027 LY_ERR ret = 0;
1028 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001029 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001030 struct lysp_ext_instance *e;
1031 enum yang_keyword kw;
1032
1033 LYSP_ARRAY_NEW_RET(ctx, exts, e, LY_EMEM);
1034
1035 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001036 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001037 e->insubstmt = insubstmt;
1038 e->insubstmt_index = insubstmt_index;
1039
1040 /* get optional argument */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001041 ret = get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001042 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001043
Radek Krejci0ae092d2018-09-20 16:43:19 +02001044 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001045 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001046 }
1047
1048 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001049 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001050
1051 ret = parse_ext_substmt(ctx, data, word, word_len, &e->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001052 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001053 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001054 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001055
1056 return ret;
1057}
1058
Michal Vaskoea5abea2018-09-18 13:10:54 +02001059/**
1060 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1061 * description, etc...
1062 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001063 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001064 * @param[in,out] data Data to read from, always moved to currently handled character.
1065 * @param[in] substmt Type of this substatement.
1066 * @param[in] substmt_index Index of this substatement.
1067 * @param[in,out] value Place to store the parsed value.
1068 * @param[in] arg Type of the YANG keyword argument (of the value).
1069 * @param[in,out] exts Extension instances to add to.
1070 *
1071 * @return LY_ERR values.
1072 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001073static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001074parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001075 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1076{
1077 LY_ERR ret = 0;
1078 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001079 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001080 enum yang_keyword kw;
1081
1082 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001083 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001084 return LY_EVALID;
1085 }
1086
1087 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001088 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001089 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001090
1091 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001092 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001093
1094 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001095 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001096
1097 switch (kw) {
1098 case YANG_CUSTOM:
1099 ret = parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001100 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001101 break;
1102 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001103 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001104 return LY_EVALID;
1105 }
1106 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001107 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001108
1109 return ret;
1110}
1111
Michal Vaskoea5abea2018-09-18 13:10:54 +02001112/**
1113 * @brief Parse the yang-version statement.
1114 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001115 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001116 * @param[in,out] data Data to read from, always moved to currently handled character.
1117 * @param[in] mod Module to store the parsed information in.
1118 *
1119 * @return LY_ERR values.
1120 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001121static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001122parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001123{
1124 LY_ERR ret = 0;
1125 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001126 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001127 enum yang_keyword kw;
1128
1129 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001130 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001131 return LY_EVALID;
1132 }
1133
1134 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001135 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001136 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001137
1138 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1139 mod->version = LYS_VERSION_1_0;
1140 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1141 mod->version = LYS_VERSION_1_1;
1142 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001143 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001144 free(buf);
1145 return LY_EVALID;
1146 }
1147 free(buf);
1148
1149 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001150 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001151
1152 switch (kw) {
1153 case YANG_CUSTOM:
1154 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001155 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001156 break;
1157 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001158 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001159 return LY_EVALID;
1160 }
1161 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001162 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001163
1164 return ret;
1165}
1166
Michal Vaskoea5abea2018-09-18 13:10:54 +02001167/**
1168 * @brief Parse the belongs-to statement.
1169 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001170 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001171 * @param[in,out] data Data to read from, always moved to currently handled character.
1172 * @param[in,out] belongsto Place to store the parsed value.
1173 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1174 * @param[in,out] exts Extension instances to add to.
1175 *
1176 * @return LY_ERR values.
1177 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001178static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001179parse_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 +02001180{
1181 LY_ERR ret = 0;
1182 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001183 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184 enum yang_keyword kw;
1185
1186 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001187 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001188 return LY_EVALID;
1189 }
1190
1191 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001192 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001193 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001194
Radek Krejci44ceedc2018-10-02 15:54:31 +02001195 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001196 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001197 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001198
1199 switch (kw) {
1200 case YANG_PREFIX:
1201 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts);
1202 break;
1203 case YANG_CUSTOM:
1204 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts);
1205 break;
1206 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001207 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001208 return LY_EVALID;
1209 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001210 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001211 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001212 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001213
1214 /* mandatory substatements */
1215 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001216 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001217 return LY_EVALID;
1218 }
1219
1220 return ret;
1221}
1222
Michal Vaskoea5abea2018-09-18 13:10:54 +02001223/**
1224 * @brief Parse the revision-date statement.
1225 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001226 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001227 * @param[in,out] data Data to read from, always moved to currently handled character.
1228 * @param[in,out] rev Array to store the parsed value in.
1229 * @param[in,out] exts Extension instances to add to.
1230 *
1231 * @return LY_ERR values.
1232 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001233static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001234parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001235{
1236 LY_ERR ret = 0;
1237 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001238 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001239 enum yang_keyword kw;
1240
1241 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001242 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001243 return LY_EVALID;
1244 }
1245
1246 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001247 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001248 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001249
1250 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001251 if (lysp_check_date(ctx->ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001252 free(buf);
1253 return LY_EVALID;
1254 }
1255
1256 /* store value and spend buf if allocated */
1257 strncpy(rev, word, word_len);
1258 free(buf);
1259
1260 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001261 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001262
1263 switch (kw) {
1264 case YANG_CUSTOM:
1265 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001266 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001267 break;
1268 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001269 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001270 return LY_EVALID;
1271 }
1272 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001273 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001274
1275 return ret;
1276}
1277
Michal Vaskoea5abea2018-09-18 13:10:54 +02001278/**
1279 * @brief Parse the include statement.
1280 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001281 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001282 * @param[in,out] data Data to read from, always moved to currently handled character.
1283 * @param[in,out] includes Parsed includes to add to.
1284 *
1285 * @return LY_ERR values.
1286 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001287static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001288parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001289{
1290 LY_ERR ret = 0;
1291 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001292 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001293 enum yang_keyword kw;
1294 struct lysp_include *inc;
1295
1296 LYSP_ARRAY_NEW_RET(ctx, includes, inc, LY_EMEM);
1297
1298 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001299 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001300 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001301
Radek Krejci44ceedc2018-10-02 15:54:31 +02001302 INSERT_WORD(ctx, buf, inc->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001303 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001304 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001305
1306 switch (kw) {
1307 case YANG_DESCRIPTION:
1308 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts);
1309 break;
1310 case YANG_REFERENCE:
1311 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts);
1312 break;
1313 case YANG_REVISION_DATE:
1314 ret = parse_revisiondate(ctx, data, inc->rev, &inc->exts);
1315 break;
1316 case YANG_CUSTOM:
1317 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts);
1318 break;
1319 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001320 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001321 return LY_EVALID;
1322 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001323 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001324 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001325 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001326
1327 return ret;
1328}
1329
Michal Vaskoea5abea2018-09-18 13:10:54 +02001330/**
1331 * @brief Parse the import statement.
1332 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001333 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001334 * @param[in,out] data Data to read from, always moved to currently handled character.
1335 * @param[in,out] imports Parsed imports to add to.
1336 *
1337 * @return LY_ERR values.
1338 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001339static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001340parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001341{
1342 LY_ERR ret = 0;
1343 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001344 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001345 enum yang_keyword kw;
1346 struct lysp_import *imp;
1347
1348 LYSP_ARRAY_NEW_RET(ctx, imports, imp, LY_EVALID);
1349
1350 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001351 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001352 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001353
Radek Krejci44ceedc2018-10-02 15:54:31 +02001354 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001355 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001356 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001357
1358 switch (kw) {
1359 case YANG_PREFIX:
1360 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts);
1361 break;
1362 case YANG_DESCRIPTION:
1363 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts);
1364 break;
1365 case YANG_REFERENCE:
1366 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts);
1367 break;
1368 case YANG_REVISION_DATE:
1369 ret = parse_revisiondate(ctx, data, imp->rev, &imp->exts);
1370 break;
1371 case YANG_CUSTOM:
1372 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts);
1373 break;
1374 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001375 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001376 return LY_EVALID;
1377 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001378 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001379 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001380 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001381
1382 /* mandatory substatements */
1383 if (!imp->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001384 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001385 return LY_EVALID;
1386 }
1387
1388 return ret;
1389}
1390
Michal Vaskoea5abea2018-09-18 13:10:54 +02001391/**
1392 * @brief Parse the revision statement.
1393 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001394 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001395 * @param[in,out] data Data to read from, always moved to currently handled character.
1396 * @param[in,out] revs Parsed revisions to add to.
1397 *
1398 * @return LY_ERR values.
1399 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001400static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001401parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001402{
1403 LY_ERR ret = 0;
1404 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001405 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001406 enum yang_keyword kw;
1407 struct lysp_revision *rev;
1408
1409 LYSP_ARRAY_NEW_RET(ctx, revs, rev, LY_EMEM);
1410
1411 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001412 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001413 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001414
1415 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001416 if (lysp_check_date(ctx->ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001417 return LY_EVALID;
1418 }
1419
1420 strncpy(rev->rev, word, word_len);
1421 free(buf);
1422
1423 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001424 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001425
1426 switch (kw) {
1427 case YANG_DESCRIPTION:
1428 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts);
1429 break;
1430 case YANG_REFERENCE:
1431 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts);
1432 break;
1433 case YANG_CUSTOM:
1434 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts);
1435 break;
1436 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001437 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001438 return LY_EVALID;
1439 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001440 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001441 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001442 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001443
1444 return ret;
1445}
1446
Michal Vaskoea5abea2018-09-18 13:10:54 +02001447/**
1448 * @brief Parse a generic text field that can have more instances such as base.
1449 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001450 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001451 * @param[in,out] data Data to read from, always moved to currently handled character.
1452 * @param[in] substmt Type of this substatement.
1453 * @param[in,out] texts Parsed values to add to.
1454 * @param[in] arg Type of the expected argument.
1455 * @param[in,out] exts Extension instances to add to.
1456 *
1457 * @return LY_ERR values.
1458 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001459static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001460parse_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 +02001461 struct lysp_ext_instance **exts)
1462{
1463 LY_ERR ret = 0;
1464 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001465 size_t count, word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001466 enum yang_keyword kw;
1467
1468 /* allocate new pointer */
1469 for (count = 1; (*texts) && (*texts)[count - 1]; ++count);
1470 *texts = realloc(*texts, count * sizeof **texts);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001471 LY_CHECK_ERR_RET(!*texts, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001472
1473 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001474 ret = get_argument(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001475 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001476
Radek Krejci44ceedc2018-10-02 15:54:31 +02001477 INSERT_WORD(ctx, buf, (*texts)[count - 1], word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001478 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001479 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001480
1481 switch (kw) {
1482 case YANG_CUSTOM:
1483 ret = parse_ext(ctx, data, word, word_len, substmt, count - 1, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001484 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001485 break;
1486 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001487 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001488 return LY_EVALID;
1489 }
1490 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001491 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001492
1493 return ret;
1494}
1495
Michal Vaskoea5abea2018-09-18 13:10:54 +02001496/**
1497 * @brief Parse the config statement.
1498 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001499 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001500 * @param[in,out] data Data to read from, always moved to currently handled character.
1501 * @param[in,out] flags Flags to add to.
1502 * @param[in,out] exts Extension instances to add to.
1503 *
1504 * @return LY_ERR values.
1505 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001506static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001507parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001508{
1509 LY_ERR ret = 0;
1510 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001511 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001512 enum yang_keyword kw;
1513
1514 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001515 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001516 return LY_EVALID;
1517 }
1518
1519 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001520 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001521 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001522
1523 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1524 *flags |= LYS_CONFIG_W;
1525 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1526 *flags |= LYS_CONFIG_R;
1527 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001528 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001529 free(buf);
1530 return LY_EVALID;
1531 }
1532 free(buf);
1533
1534 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001535 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001536
1537 switch (kw) {
1538 case YANG_CUSTOM:
1539 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001540 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001541 break;
1542 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001543 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001544 return LY_EVALID;
1545 }
1546 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001547 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001548
1549 return ret;
1550}
1551
Michal Vaskoea5abea2018-09-18 13:10:54 +02001552/**
1553 * @brief Parse the mandatory statement.
1554 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001555 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001556 * @param[in,out] data Data to read from, always moved to currently handled character.
1557 * @param[in,out] flags Flags to add to.
1558 * @param[in,out] exts Extension instances to add to.
1559 *
1560 * @return LY_ERR values.
1561 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001562static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001563parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001564{
1565 LY_ERR ret = 0;
1566 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001567 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001568 enum yang_keyword kw;
1569
1570 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001571 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001572 return LY_EVALID;
1573 }
1574
1575 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001576 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001577 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001578
1579 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1580 *flags |= LYS_MAND_TRUE;
1581 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1582 *flags |= LYS_MAND_FALSE;
1583 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001584 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001585 free(buf);
1586 return LY_EVALID;
1587 }
1588 free(buf);
1589
1590 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001591 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001592
1593 switch (kw) {
1594 case YANG_CUSTOM:
1595 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001596 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001597 break;
1598 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001599 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001600 return LY_EVALID;
1601 }
1602 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001603 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001604
1605 return ret;
1606}
1607
Michal Vaskoea5abea2018-09-18 13:10:54 +02001608/**
1609 * @brief Parse a restriction such as range or length.
1610 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001611 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001612 * @param[in,out] data Data to read from, always moved to currently handled character.
1613 * @param[in] restr_kw Type of this particular restriction.
1614 * @param[in,out] exts Extension instances to add to.
1615 *
1616 * @return LY_ERR values.
1617 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001618static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001619parse_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 +02001620{
1621 LY_ERR ret = 0;
1622 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001623 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001624 enum yang_keyword kw;
1625
1626 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001627 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001628 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001629
Radek Krejci44ceedc2018-10-02 15:54:31 +02001630 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001631 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001632 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001633
1634 switch (kw) {
1635 case YANG_DESCRIPTION:
1636 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
1637 break;
1638 case YANG_REFERENCE:
1639 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
1640 break;
1641 case YANG_ERROR_APP_TAG:
1642 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
1643 break;
1644 case YANG_ERROR_MESSAGE:
1645 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
1646 break;
1647 case YANG_CUSTOM:
1648 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
1649 break;
1650 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001651 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001652 return LY_EVALID;
1653 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001654 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001655 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001656 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001657
1658 return ret;
1659}
1660
Michal Vaskoea5abea2018-09-18 13:10:54 +02001661/**
1662 * @brief Parse a restriction that can have more instances such as must.
1663 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001664 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001665 * @param[in,out] data Data to read from, always moved to currently handled character.
1666 * @param[in] restr_kw Type of this particular restriction.
1667 * @param[in,out] restrs Restrictions to add to.
1668 *
1669 * @return LY_ERR values.
1670 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001671static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001672parse_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 +02001673{
1674 struct lysp_restr *restr;
1675
1676 LYSP_ARRAY_NEW_RET(ctx, restrs, restr, LY_EMEM);
1677
1678 return parse_restr(ctx, data, restr_kw, restr);
1679}
1680
Michal Vaskoea5abea2018-09-18 13:10:54 +02001681/**
1682 * @brief Parse the status statement.
1683 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001684 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001685 * @param[in,out] data Data to read from, always moved to currently handled character.
1686 * @param[in,out] flags Flags to add to.
1687 * @param[in,out] exts Extension instances to add to.
1688 *
1689 * @return LY_ERR values.
1690 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001691static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001692parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001693{
1694 LY_ERR ret = 0;
1695 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001696 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001697 enum yang_keyword kw;
1698
1699 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001700 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001701 return LY_EVALID;
1702 }
1703
1704 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001705 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001706 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001707
1708 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1709 *flags |= LYS_STATUS_CURR;
1710 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1711 *flags |= LYS_STATUS_DEPRC;
1712 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1713 *flags |= LYS_STATUS_OBSLT;
1714 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001715 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001716 free(buf);
1717 return LY_EVALID;
1718 }
1719 free(buf);
1720
1721 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001722 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001723
1724 switch (kw) {
1725 case YANG_CUSTOM:
1726 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001727 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001728 break;
1729 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001730 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001731 return LY_EVALID;
1732 }
1733 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001734 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001735
1736 return ret;
1737}
1738
Michal Vaskoea5abea2018-09-18 13:10:54 +02001739/**
1740 * @brief Parse the when statement.
1741 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001742 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001743 * @param[in,out] data Data to read from, always moved to currently handled character.
1744 * @param[in,out] when_p When pointer to parse to.
1745 *
1746 * @return LY_ERR values.
1747 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001748static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001749parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001750{
1751 LY_ERR ret = 0;
1752 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001753 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001754 enum yang_keyword kw;
1755 struct lysp_when *when;
1756
1757 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001758 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001759 return LY_EVALID;
1760 }
1761
1762 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001763 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001764 *when_p = when;
1765
1766 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001767 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001768 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001769
Radek Krejci44ceedc2018-10-02 15:54:31 +02001770 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001771 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001772 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001773
1774 switch (kw) {
1775 case YANG_DESCRIPTION:
1776 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts);
1777 break;
1778 case YANG_REFERENCE:
1779 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts);
1780 break;
1781 case YANG_CUSTOM:
1782 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts);
1783 break;
1784 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001785 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001786 return LY_EVALID;
1787 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001788 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001789 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001790 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001791
1792 return ret;
1793}
1794
Michal Vaskoea5abea2018-09-18 13:10:54 +02001795/**
1796 * @brief Parse the anydata or anyxml statement.
1797 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001798 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001799 * @param[in,out] data Data to read from, always moved to currently handled character.
1800 * @param[in] kw Type of this particular keyword.
1801 * @param[in,out] siblings Siblings to add to.
1802 *
1803 * @return LY_ERR values.
1804 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001805static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001806parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001807{
1808 LY_ERR ret = 0;
1809 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001810 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001811 struct lysp_node *iter;
1812 struct lysp_node_anydata *any;
1813
1814 /* create structure */
1815 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001816 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001817 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
1818
1819 /* insert into siblings */
1820 if (!*siblings) {
1821 *siblings = (struct lysp_node *)any;
1822 } else {
1823 for (iter = *siblings; iter->next; iter = iter->next);
1824 iter->next = (struct lysp_node *)any;
1825 }
1826
1827 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001828 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001829 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001830
Radek Krejci44ceedc2018-10-02 15:54:31 +02001831 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001832
1833 /* parse substatements */
1834 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001835 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001836
1837 switch (kw) {
1838 case YANG_CONFIG:
1839 ret = parse_config(ctx, data, &any->flags, &any->exts);
1840 break;
1841 case YANG_DESCRIPTION:
1842 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts);
1843 break;
1844 case YANG_IF_FEATURE:
1845 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts);
1846 break;
1847 case YANG_MANDATORY:
1848 ret = parse_mandatory(ctx, data, &any->flags, &any->exts);
1849 break;
1850 case YANG_MUST:
1851 ret = parse_restrs(ctx, data, kw, &any->musts);
1852 break;
1853 case YANG_REFERENCE:
1854 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts);
1855 break;
1856 case YANG_STATUS:
1857 ret = parse_status(ctx, data, &any->flags, &any->exts);
1858 break;
1859 case YANG_WHEN:
1860 ret = parse_when(ctx, data, &any->when);
1861 break;
1862 case YANG_CUSTOM:
1863 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts);
1864 break;
1865 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001866 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001867 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001868 return LY_EVALID;
1869 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001870 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001871 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001872 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001873
1874 return ret;
1875}
1876
Michal Vaskoea5abea2018-09-18 13:10:54 +02001877/**
1878 * @brief Parse the value or position statement. Substatement of type enum statement.
1879 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001880 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001881 * @param[in,out] data Data to read from, always moved to currently handled character.
1882 * @param[in] val_kw Type of this particular keyword.
1883 * @param[in,out] value Value to write to.
1884 * @param[in,out] flags Flags to write to.
1885 * @param[in,out] exts Extension instances to add to.
1886 *
1887 * @return LY_ERR values.
1888 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001889static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001890parse_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 +02001891 struct lysp_ext_instance **exts)
1892{
1893 LY_ERR ret = 0;
1894 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001895 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001896 long int num;
1897 unsigned long int unum;
1898 enum yang_keyword kw;
1899
1900 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001901 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001902 return LY_EVALID;
1903 }
1904 *flags |= LYS_SET_VALUE;
1905
1906 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001907 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001908 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001909
1910 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 +02001911 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001912 free(buf);
1913 return LY_EVALID;
1914 }
1915
1916 errno = 0;
1917 if (val_kw == YANG_VALUE) {
1918 num = strtol(word, &ptr, 10);
1919 } else {
1920 unum = strtoul(word, &ptr, 10);
1921 }
1922 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001923 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001924 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001925 free(buf);
1926 return LY_EVALID;
1927 }
1928 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001929 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001930 free(buf);
1931 return LY_EVALID;
1932 }
1933 if (val_kw == YANG_VALUE) {
1934 *value = num;
1935 } else {
1936 *value = unum;
1937 }
1938 free(buf);
1939
1940 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001941 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001942
1943 switch (kw) {
1944 case YANG_CUSTOM:
1945 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 +02001946 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001947 break;
1948 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001949 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001950 return LY_EVALID;
1951 }
1952 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001953 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001954
1955 return ret;
1956}
1957
Michal Vaskoea5abea2018-09-18 13:10:54 +02001958/**
1959 * @brief Parse the enum or bit statement. Substatement of type statement.
1960 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001961 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001962 * @param[in,out] data Data to read from, always moved to currently handled character.
1963 * @param[in] enum_kw Type of this particular keyword.
1964 * @param[in,out] enums Enums or bits to add to.
1965 *
1966 * @return LY_ERR values.
1967 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001968static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001969parse_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 +02001970{
1971 LY_ERR ret = 0;
1972 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001973 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001974 enum yang_keyword kw;
1975 struct lysp_type_enum *enm;
1976
1977 LYSP_ARRAY_NEW_RET(ctx, enums, enm, LY_EMEM);
1978
1979 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02001980 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001981 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001982
Radek Krejci44ceedc2018-10-02 15:54:31 +02001983 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001984 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001985 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001986
1987 switch (kw) {
1988 case YANG_DESCRIPTION:
1989 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts);
1990 break;
1991 case YANG_IF_FEATURE:
1992 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts);
1993 break;
1994 case YANG_REFERENCE:
1995 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts);
1996 break;
1997 case YANG_STATUS:
1998 ret = parse_status(ctx, data, &enm->flags, &enm->exts);
1999 break;
2000 case YANG_VALUE:
2001 case YANG_POSITION:
2002 ret = parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts);
2003 break;
2004 case YANG_CUSTOM:
2005 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts);
2006 break;
2007 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002008 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002009 return LY_EVALID;
2010 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002011 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002012 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002013 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002014
2015 return ret;
2016}
2017
Michal Vaskoea5abea2018-09-18 13:10:54 +02002018/**
2019 * @brief Parse the fraction-digits statement. Substatement of type statement.
2020 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002021 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002022 * @param[in,out] data Data to read from, always moved to currently handled character.
2023 * @param[in,out] fracdig Value to write to.
2024 * @param[in,out] exts Extension instances to add to.
2025 *
2026 * @return LY_ERR values.
2027 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002028static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002029parse_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 +02002030{
2031 LY_ERR ret = 0;
2032 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002033 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002034 unsigned long int num;
2035 enum yang_keyword kw;
2036
2037 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002038 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002039 return LY_EVALID;
2040 }
2041
2042 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002043 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002044 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002045
2046 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002047 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002048 free(buf);
2049 return LY_EVALID;
2050 }
2051
2052 errno = 0;
2053 num = strtoul(word, &ptr, 10);
2054 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002055 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002056 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002057 free(buf);
2058 return LY_EVALID;
2059 }
2060 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002061 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002062 free(buf);
2063 return LY_EVALID;
2064 }
2065 *fracdig = num;
2066 free(buf);
2067
2068 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002069 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002070
2071 switch (kw) {
2072 case YANG_CUSTOM:
2073 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002074 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002075 break;
2076 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002077 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002078 return LY_EVALID;
2079 }
2080 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002081 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002082
2083 return ret;
2084}
2085
Michal Vaskoea5abea2018-09-18 13:10:54 +02002086/**
2087 * @brief Parse the require-instance statement. Substatement of type statement.
2088 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002089 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002090 * @param[in,out] data Data to read from, always moved to currently handled character.
2091 * @param[in,out] reqinst Value to write to.
2092 * @param[in,out] flags Flags to write to.
2093 * @param[in,out] exts Extension instances to add to.
2094 *
2095 * @return LY_ERR values.
2096 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002097static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002098parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002099 struct lysp_ext_instance **exts)
2100{
2101 LY_ERR ret = 0;
2102 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002103 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002104 enum yang_keyword kw;
2105
2106 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002107 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002108 return LY_EVALID;
2109 }
2110 *flags |= LYS_SET_REQINST;
2111
2112 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002113 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002114 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002115
2116 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2117 *reqinst = 1;
2118 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002119 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002120 free(buf);
2121 return LY_EVALID;
2122 }
2123 free(buf);
2124
2125 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002126 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002127
2128 switch (kw) {
2129 case YANG_CUSTOM:
2130 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002131 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002132 break;
2133 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002134 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002135 return LY_EVALID;
2136 }
2137 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002138 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002139
2140 return ret;
2141}
2142
Michal Vaskoea5abea2018-09-18 13:10:54 +02002143/**
2144 * @brief Parse the modifier statement. Substatement of type pattern statement.
2145 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002146 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002147 * @param[in,out] data Data to read from, always moved to currently handled character.
2148 * @param[in,out] pat Value to write to.
2149 * @param[in,out] exts Extension instances to add to.
2150 *
2151 * @return LY_ERR values.
2152 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002153static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002154parse_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 +02002155{
2156 LY_ERR ret = 0;
2157 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002158 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002159 enum yang_keyword kw;
2160
2161 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002162 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002163 return LY_EVALID;
2164 }
2165
2166 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002167 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002168 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002169
2170 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002171 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002172 free(buf);
2173 return LY_EVALID;
2174 }
2175 free(buf);
2176
2177 /* replace the value in the dictionary */
2178 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002179 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002180 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002181 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002182
2183 assert(buf[0] == 0x06);
2184 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002185 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002186
2187 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002188 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189
2190 switch (kw) {
2191 case YANG_CUSTOM:
2192 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002193 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002194 break;
2195 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002196 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002197 return LY_EVALID;
2198 }
2199 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002200 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002201
2202 return ret;
2203}
2204
Michal Vaskoea5abea2018-09-18 13:10:54 +02002205/**
2206 * @brief Parse the pattern statement. Substatement of type statement.
2207 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002208 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002209 * @param[in,out] data Data to read from, always moved to currently handled character.
2210 * @param[in,out] patterns Restrictions to add to.
2211 *
2212 * @return LY_ERR values.
2213 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002214static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002215parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002216{
2217 LY_ERR ret = 0;
2218 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002219 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002220 enum yang_keyword kw;
2221 struct lysp_restr *restr;
2222
2223 LYSP_ARRAY_NEW_RET(ctx, patterns, restr, LY_EMEM);
2224
2225 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002226 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002227 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002228
2229 /* add special meaning first byte */
2230 if (buf) {
2231 buf = realloc(buf, word_len + 2);
2232 word = buf;
2233 } else {
2234 buf = malloc(word_len + 2);
2235 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002236 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002237 memmove(buf + 1, word, word_len + 1);
2238 word[0] = 0x06;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002239 restr->arg = lydict_insert_zc(ctx->ctx, word);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002240
2241 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002242 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002243
2244 switch (kw) {
2245 case YANG_DESCRIPTION:
2246 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
2247 break;
2248 case YANG_REFERENCE:
2249 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
2250 break;
2251 case YANG_ERROR_APP_TAG:
2252 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
2253 break;
2254 case YANG_ERROR_MESSAGE:
2255 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
2256 break;
2257 case YANG_MODIFIER:
2258 ret = parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts);
2259 break;
2260 case YANG_CUSTOM:
2261 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
2262 break;
2263 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002264 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002265 return LY_EVALID;
2266 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002267 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002268 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002269 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002270
2271 return ret;
2272}
2273
Michal Vaskoea5abea2018-09-18 13:10:54 +02002274/**
2275 * @brief Parse the type statement.
2276 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002277 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002278 * @param[in,out] data Data to read from, always moved to currently handled character.
2279 * @param[in,out] type Type to wrote to.
2280 *
2281 * @return LY_ERR values.
2282 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002283static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002284parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002285{
2286 LY_ERR ret = 0;
2287 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002288 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002289 enum yang_keyword kw;
2290 struct lysp_type *nest_type;
2291
2292 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002293 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002294 return LY_EVALID;
2295 }
2296
2297 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002298 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002299 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002300
Radek Krejci44ceedc2018-10-02 15:54:31 +02002301 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002302 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002303 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002304
2305 switch (kw) {
2306 case YANG_BASE:
2307 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts);
2308 break;
2309 case YANG_BIT:
2310 ret = parse_type_enum(ctx, data, kw, &type->bits);
2311 break;
2312 case YANG_ENUM:
2313 ret = parse_type_enum(ctx, data, kw, &type->enums);
2314 break;
2315 case YANG_FRACTION_DIGITS:
2316 ret = parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts);
2317 break;
2318 case YANG_LENGTH:
2319 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002320 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002321 return LY_EVALID;
2322 }
2323 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002324 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002325
2326 ret = parse_restr(ctx, data, kw, type->length);
2327 break;
2328 case YANG_PATH:
2329 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts);
2330 break;
2331 case YANG_PATTERN:
2332 ret = parse_type_pattern(ctx, data, &type->patterns);
2333 break;
2334 case YANG_RANGE:
2335 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002336 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002337 return LY_EVALID;
2338 }
2339 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002340 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002341
2342 ret = parse_restr(ctx, data, kw, type->range);
2343 break;
2344 case YANG_REQUIRE_INSTANCE:
2345 ret = parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts);
2346 break;
2347 case YANG_TYPE:
2348 {
2349 LYSP_ARRAY_NEW_RET(ctx, &type->types, nest_type, LY_EMEM);
2350 }
2351 ret = parse_type(ctx, data, nest_type);
2352 break;
2353 case YANG_CUSTOM:
2354 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts);
2355 break;
2356 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002357 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002358 return LY_EVALID;
2359 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002360 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002361 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002362 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002363
2364 return ret;
2365}
2366
Michal Vaskoea5abea2018-09-18 13:10:54 +02002367/**
2368 * @brief Parse the leaf statement.
2369 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002370 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002371 * @param[in,out] data Data to read from, always moved to currently handled character.
2372 * @param[in,out] siblings Siblings to add to.
2373 *
2374 * @return LY_ERR values.
2375 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002376static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002377parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002378{
2379 LY_ERR ret = 0;
2380 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002381 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002382 enum yang_keyword kw;
2383 struct lysp_node *iter;
2384 struct lysp_node_leaf *leaf;
2385
2386 /* create structure */
2387 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002388 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002389 leaf->nodetype = LYS_LEAF;
2390
2391 /* insert into siblings */
2392 if (!*siblings) {
2393 *siblings = (struct lysp_node *)leaf;
2394 } else {
2395 for (iter = *siblings; iter->next; iter = iter->next);
2396 iter->next = (struct lysp_node *)leaf;
2397 }
2398
2399 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002400 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002401 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002402
Radek Krejci44ceedc2018-10-02 15:54:31 +02002403 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002404
2405 /* parse substatements */
2406 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002407 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002408
2409 switch (kw) {
2410 case YANG_CONFIG:
2411 ret = parse_config(ctx, data, &leaf->flags, &leaf->exts);
2412 break;
2413 case YANG_DEFAULT:
2414 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts);
2415 break;
2416 case YANG_DESCRIPTION:
2417 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts);
2418 break;
2419 case YANG_IF_FEATURE:
2420 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts);
2421 break;
2422 case YANG_MANDATORY:
2423 ret = parse_mandatory(ctx, data, &leaf->flags, &leaf->exts);
2424 break;
2425 case YANG_MUST:
2426 ret = parse_restrs(ctx, data, kw, &leaf->musts);
2427 break;
2428 case YANG_REFERENCE:
2429 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts);
2430 break;
2431 case YANG_STATUS:
2432 ret = parse_status(ctx, data, &leaf->flags, &leaf->exts);
2433 break;
2434 case YANG_TYPE:
2435 ret = parse_type(ctx, data, &leaf->type);
2436 break;
2437 case YANG_UNITS:
2438 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts);
2439 break;
2440 case YANG_WHEN:
2441 ret = parse_when(ctx, data, &leaf->when);
2442 break;
2443 case YANG_CUSTOM:
2444 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts);
2445 break;
2446 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002447 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002448 return LY_EVALID;
2449 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002450 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002451 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002452 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002453
2454 /* mandatory substatements */
2455 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002456 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002457 return LY_EVALID;
2458 }
2459
2460 return ret;
2461}
2462
Michal Vaskoea5abea2018-09-18 13:10:54 +02002463/**
2464 * @brief Parse the max-elements statement.
2465 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002466 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002467 * @param[in,out] data Data to read from, always moved to currently handled character.
2468 * @param[in,out] max Value to write to.
2469 * @param[in,out] flags Flags to write to.
2470 * @param[in,out] exts Extension instances to add to.
2471 *
2472 * @return LY_ERR values.
2473 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002474static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002475parse_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 +02002476{
2477 LY_ERR ret = 0;
2478 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002479 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002480 unsigned long int num;
2481 enum yang_keyword kw;
2482
2483 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002484 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002485 return LY_EVALID;
2486 }
2487 *flags |= LYS_SET_MAX;
2488
2489 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002490 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002491 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002492
2493 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002494 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002495 free(buf);
2496 return LY_EVALID;
2497 }
2498
2499 if (strncmp(word, "unbounded", word_len)) {
2500 errno = 0;
2501 num = strtoul(word, &ptr, 10);
2502 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002503 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002504 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002505 free(buf);
2506 return LY_EVALID;
2507 }
2508 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002509 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002510 free(buf);
2511 return LY_EVALID;
2512 }
2513
2514 *max = num;
2515 }
2516 free(buf);
2517
2518 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002519 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002520
2521 switch (kw) {
2522 case YANG_CUSTOM:
2523 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002524 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002525 break;
2526 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002527 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002528 return LY_EVALID;
2529 }
2530 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002531 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002532
2533 return ret;
2534}
2535
Michal Vaskoea5abea2018-09-18 13:10:54 +02002536/**
2537 * @brief Parse the min-elements statement.
2538 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002539 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002540 * @param[in,out] data Data to read from, always moved to currently handled character.
2541 * @param[in,out] min Value to write to.
2542 * @param[in,out] flags Flags to write to.
2543 * @param[in,out] exts Extension instances to add to.
2544 *
2545 * @return LY_ERR values.
2546 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002547static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002548parse_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 +02002549{
2550 LY_ERR ret = 0;
2551 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002552 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002553 unsigned long int num;
2554 enum yang_keyword kw;
2555
2556 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002557 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002558 return LY_EVALID;
2559 }
2560 *flags |= LYS_SET_MIN;
2561
2562 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002563 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002564 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002565
2566 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002567 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002568 free(buf);
2569 return LY_EVALID;
2570 }
2571
2572 errno = 0;
2573 num = strtoul(word, &ptr, 10);
2574 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002575 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002576 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002577 free(buf);
2578 return LY_EVALID;
2579 }
2580 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002581 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002582 free(buf);
2583 return LY_EVALID;
2584 }
2585 *min = num;
2586 free(buf);
2587
2588 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002589 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002590
2591 switch (kw) {
2592 case YANG_CUSTOM:
2593 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002594 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002595 break;
2596 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002597 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002598 return LY_EVALID;
2599 }
2600 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002601 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002602
2603 return ret;
2604}
2605
Michal Vaskoea5abea2018-09-18 13:10:54 +02002606/**
2607 * @brief Parse the ordered-by statement.
2608 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002609 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002610 * @param[in,out] data Data to read from, always moved to currently handled character.
2611 * @param[in,out] flags Flags to write to.
2612 * @param[in,out] exts Extension instances to add to.
2613 *
2614 * @return LY_ERR values.
2615 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002616static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002617parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002618{
2619 LY_ERR ret = 0;
2620 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002621 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002622 enum yang_keyword kw;
2623
2624 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002625 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002626 return LY_EVALID;
2627 }
2628
2629 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002630 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002631 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002632
2633 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2634 *flags |= LYS_ORDBY_SYSTEM;
2635 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2636 *flags |= LYS_ORDBY_USER;
2637 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002638 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002639 free(buf);
2640 return LY_EVALID;
2641 }
2642 free(buf);
2643
2644 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002645 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002646
2647 switch (kw) {
2648 case YANG_CUSTOM:
2649 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002650 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002651 break;
2652 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002653 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002654 return LY_EVALID;
2655 }
2656 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002657 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002658
2659 return ret;
2660}
2661
Michal Vaskoea5abea2018-09-18 13:10:54 +02002662/**
2663 * @brief Parse the leaf-list statement.
2664 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002665 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002666 * @param[in,out] data Data to read from, always moved to currently handled character.
2667 * @param[in,out] siblings Siblings to add to.
2668 *
2669 * @return LY_ERR values.
2670 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002671static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002672parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002673{
2674 LY_ERR ret = 0;
2675 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002676 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002677 enum yang_keyword kw;
2678 struct lysp_node *iter;
2679 struct lysp_node_leaflist *llist;
2680
2681 /* create structure */
2682 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002683 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002684 llist->nodetype = LYS_LEAFLIST;
2685
2686 /* insert into siblings */
2687 if (!*siblings) {
2688 *siblings = (struct lysp_node *)llist;
2689 } else {
2690 for (iter = *siblings; iter->next; iter = iter->next);
2691 iter->next = (struct lysp_node *)llist;
2692 }
2693
2694 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002695 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002696 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002697
Radek Krejci44ceedc2018-10-02 15:54:31 +02002698 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002699
2700 /* parse substatements */
2701 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002702 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002703
2704 switch (kw) {
2705 case YANG_CONFIG:
2706 ret = parse_config(ctx, data, &llist->flags, &llist->exts);
2707 break;
2708 case YANG_DEFAULT:
2709 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts);
2710 break;
2711 case YANG_DESCRIPTION:
2712 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts);
2713 break;
2714 case YANG_IF_FEATURE:
2715 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts);
2716 break;
2717 case YANG_MAX_ELEMENTS:
2718 ret = parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts);
2719 break;
2720 case YANG_MIN_ELEMENTS:
2721 ret = parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts);
2722 break;
2723 case YANG_MUST:
2724 ret = parse_restrs(ctx, data, kw, &llist->musts);
2725 break;
2726 case YANG_ORDERED_BY:
2727 ret = parse_orderedby(ctx, data, &llist->flags, &llist->exts);
2728 break;
2729 case YANG_REFERENCE:
2730 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts);
2731 break;
2732 case YANG_STATUS:
2733 ret = parse_status(ctx, data, &llist->flags, &llist->exts);
2734 break;
2735 case YANG_TYPE:
2736 ret = parse_type(ctx, data, &llist->type);
2737 break;
2738 case YANG_UNITS:
2739 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts);
2740 break;
2741 case YANG_WHEN:
2742 ret = parse_when(ctx, data, &llist->when);
2743 break;
2744 case YANG_CUSTOM:
2745 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts);
2746 break;
2747 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002748 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002749 return LY_EVALID;
2750 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002751 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002752 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002753 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002754
2755 /* mandatory substatements */
2756 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002757 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002758 return LY_EVALID;
2759 }
2760
2761 return ret;
2762}
2763
Michal Vaskoea5abea2018-09-18 13:10:54 +02002764/**
2765 * @brief Parse the refine statement.
2766 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002767 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002768 * @param[in,out] data Data to read from, always moved to currently handled character.
2769 * @param[in,out] refines Refines to add to.
2770 *
2771 * @return LY_ERR values.
2772 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002773static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002774parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002775{
2776 LY_ERR ret = 0;
2777 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002778 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002779 enum yang_keyword kw;
2780 struct lysp_refine *rf;
2781
2782 LYSP_ARRAY_NEW_RET(ctx, refines, rf, LY_EMEM);
2783
2784 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002785 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002786 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002787
Radek Krejci44ceedc2018-10-02 15:54:31 +02002788 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002789 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002790 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002791
2792 switch (kw) {
2793 case YANG_CONFIG:
2794 ret = parse_config(ctx, data, &rf->flags, &rf->exts);
2795 break;
2796 case YANG_DEFAULT:
2797 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts);
2798 break;
2799 case YANG_DESCRIPTION:
2800 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts);
2801 break;
2802 case YANG_IF_FEATURE:
2803 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts);
2804 break;
2805 case YANG_MAX_ELEMENTS:
2806 ret = parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts);
2807 break;
2808 case YANG_MIN_ELEMENTS:
2809 ret = parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts);
2810 break;
2811 case YANG_MUST:
2812 ret = parse_restrs(ctx, data, kw, &rf->musts);
2813 break;
2814 case YANG_MANDATORY:
2815 ret = parse_mandatory(ctx, data, &rf->flags, &rf->exts);
2816 break;
2817 case YANG_REFERENCE:
2818 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts);
2819 break;
2820 case YANG_PRESENCE:
2821 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts);
2822 break;
2823 case YANG_CUSTOM:
2824 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts);
2825 break;
2826 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002827 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002828 return LY_EVALID;
2829 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002830 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002831 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002832 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002833
2834 return ret;
2835}
2836
Michal Vaskoea5abea2018-09-18 13:10:54 +02002837/**
2838 * @brief Parse the typedef statement.
2839 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002840 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002841 * @param[in,out] data Data to read from, always moved to currently handled character.
2842 * @param[in,out] typedefs Typedefs to add to.
2843 *
2844 * @return LY_ERR values.
2845 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002846static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002847parse_typedef(struct ly_parser_ctx *ctx, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002848{
2849 LY_ERR ret = 0;
2850 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002851 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002852 enum yang_keyword kw;
2853 struct lysp_tpdf *tpdf;
2854
2855 LYSP_ARRAY_NEW_RET(ctx, typedefs, tpdf, LY_EMEM);
2856
2857 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02002858 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002859 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860
Radek Krejci44ceedc2018-10-02 15:54:31 +02002861 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002862
2863 /* parse substatements */
2864 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002865 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002866
2867 switch (kw) {
2868 case YANG_DEFAULT:
2869 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts);
2870 break;
2871 case YANG_DESCRIPTION:
2872 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts);
2873 break;
2874 case YANG_REFERENCE:
2875 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts);
2876 break;
2877 case YANG_STATUS:
2878 ret = parse_status(ctx, data, &tpdf->flags, &tpdf->exts);
2879 break;
2880 case YANG_TYPE:
2881 ret = parse_type(ctx, data, &tpdf->type);
2882 break;
2883 case YANG_UNITS:
2884 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts);
2885 break;
2886 case YANG_CUSTOM:
2887 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts);
2888 break;
2889 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002890 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002891 return LY_EVALID;
2892 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002893 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002894 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002895 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002896
2897 /* mandatory substatements */
2898 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002899 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002900 return LY_EVALID;
2901 }
2902
2903 return ret;
2904}
2905
Michal Vaskoea5abea2018-09-18 13:10:54 +02002906/**
2907 * @brief Parse the input or output statement.
2908 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002909 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002910 * @param[in,out] data Data to read from, always moved to currently handled character.
2911 * @param[in] kw Type of this particular keyword
2912 * @param[in,out] inout_p Input/output pointer to write to.
2913 *
2914 * @return LY_ERR values.
2915 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002916static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002917parse_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 +02002918{
2919 LY_ERR ret = 0;
2920 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002921 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002922 struct lysp_action_inout *inout;
2923
2924 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002925 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002926 return LY_EVALID;
2927 }
2928
2929 /* create structure */
2930 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002931 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002932 *inout_p = inout;
2933
2934 /* parse substatements */
2935 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002936 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002937
2938 switch (kw) {
2939 case YANG_ANYDATA:
2940 case YANG_ANYXML:
2941 ret = parse_any(ctx, data, kw, &inout->data);
2942 break;
2943 case YANG_CHOICE:
2944 ret = parse_choice(ctx, data, &inout->data);
2945 break;
2946 case YANG_CONTAINER:
2947 ret = parse_container(ctx, data, &inout->data);
2948 break;
2949 case YANG_LEAF:
2950 ret = parse_leaf(ctx, data, &inout->data);
2951 break;
2952 case YANG_LEAF_LIST:
2953 ret = parse_leaflist(ctx, data, &inout->data);
2954 break;
2955 case YANG_LIST:
2956 ret = parse_list(ctx, data, &inout->data);
2957 break;
2958 case YANG_USES:
2959 ret = parse_uses(ctx, data, &inout->data);
2960 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002961 case YANG_TYPEDEF:
2962 ret = parse_typedef(ctx, data, &inout->typedefs);
2963 break;
2964 case YANG_MUST:
2965 ret = parse_restrs(ctx, data, kw, &inout->musts);
2966 break;
2967 case YANG_GROUPING:
2968 ret = parse_grouping(ctx, data, &inout->groupings);
2969 break;
2970 case YANG_CUSTOM:
2971 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts);
2972 break;
2973 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002974 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002975 return LY_EVALID;
2976 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002977 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002979 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002980
2981 return ret;
2982}
2983
Michal Vaskoea5abea2018-09-18 13:10:54 +02002984/**
2985 * @brief Parse the action statement.
2986 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002987 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002988 * @param[in,out] data Data to read from, always moved to currently handled character.
2989 * @param[in,out] actions Actions to add to.
2990 *
2991 * @return LY_ERR values.
2992 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002993static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002994parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002995{
2996 LY_ERR ret = 0;
2997 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002998 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002999 enum yang_keyword kw;
3000 struct lysp_action *act;
3001
3002 LYSP_ARRAY_NEW_RET(ctx, actions, act, LY_EMEM);
3003
3004 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003005 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003006 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003007
Radek Krejci44ceedc2018-10-02 15:54:31 +02003008 INSERT_WORD(ctx, buf, act->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003009 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003010 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003011
3012 switch (kw) {
3013 case YANG_DESCRIPTION:
3014 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts);
3015 break;
3016 case YANG_IF_FEATURE:
3017 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts);
3018 break;
3019 case YANG_REFERENCE:
3020 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts);
3021 break;
3022 case YANG_STATUS:
3023 ret = parse_status(ctx, data, &act->flags, &act->exts);
3024 break;
3025
3026 case YANG_INPUT:
3027 ret = parse_inout(ctx, data, kw, &act->input);
3028 break;
3029 case YANG_OUTPUT:
3030 ret = parse_inout(ctx, data, kw, &act->output);
3031 break;
3032
3033 case YANG_TYPEDEF:
3034 ret = parse_typedef(ctx, data, &act->typedefs);
3035 break;
3036 case YANG_GROUPING:
3037 ret = parse_grouping(ctx, data, &act->groupings);
3038 break;
3039 case YANG_CUSTOM:
3040 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts);
3041 break;
3042 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003043 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003044 return LY_EVALID;
3045 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003046 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003047 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003048 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003049
3050 return ret;
3051}
3052
Michal Vaskoea5abea2018-09-18 13:10:54 +02003053/**
3054 * @brief Parse the notification statement.
3055 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003056 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003057 * @param[in,out] data Data to read from, always moved to currently handled character.
3058 * @param[in,out] notifs Notifications to add to.
3059 *
3060 * @return LY_ERR values.
3061 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003062static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003063parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003064{
3065 LY_ERR ret = 0;
3066 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003067 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003068 enum yang_keyword kw;
3069 struct lysp_notif *notif;
3070
3071 LYSP_ARRAY_NEW_RET(ctx, notifs, notif, LY_EMEM);
3072
3073 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003074 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003075 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076
Radek Krejci44ceedc2018-10-02 15:54:31 +02003077 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003078 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003079 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003080
3081 switch (kw) {
3082 case YANG_DESCRIPTION:
3083 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts);
3084 break;
3085 case YANG_IF_FEATURE:
3086 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts);
3087 break;
3088 case YANG_REFERENCE:
3089 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts);
3090 break;
3091 case YANG_STATUS:
3092 ret = parse_status(ctx, data, &notif->flags, &notif->exts);
3093 break;
3094
3095 case YANG_ANYDATA:
3096 case YANG_ANYXML:
3097 ret = parse_any(ctx, data, kw, &notif->data);
3098 break;
3099 case YANG_CHOICE:
3100 ret = parse_case(ctx, data, &notif->data);
3101 break;
3102 case YANG_CONTAINER:
3103 ret = parse_container(ctx, data, &notif->data);
3104 break;
3105 case YANG_LEAF:
3106 ret = parse_leaf(ctx, data, &notif->data);
3107 break;
3108 case YANG_LEAF_LIST:
3109 ret = parse_leaflist(ctx, data, &notif->data);
3110 break;
3111 case YANG_LIST:
3112 ret = parse_list(ctx, data, &notif->data);
3113 break;
3114 case YANG_USES:
3115 ret = parse_uses(ctx, data, &notif->data);
3116 break;
3117
3118 case YANG_MUST:
3119 ret = parse_restrs(ctx, data, kw, &notif->musts);
3120 break;
3121 case YANG_TYPEDEF:
3122 ret = parse_typedef(ctx, data, &notif->typedefs);
3123 break;
3124 case YANG_GROUPING:
3125 ret = parse_grouping(ctx, data, &notif->groupings);
3126 break;
3127 case YANG_CUSTOM:
3128 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts);
3129 break;
3130 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003131 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003132 return LY_EVALID;
3133 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003134 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003136 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003137
3138 return ret;
3139}
3140
Michal Vaskoea5abea2018-09-18 13:10:54 +02003141/**
3142 * @brief Parse the grouping statement.
3143 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003144 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003145 * @param[in,out] data Data to read from, always moved to currently handled character.
3146 * @param[in,out] groupings Groupings to add to.
3147 *
3148 * @return LY_ERR values.
3149 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003150static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003151parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003152{
3153 LY_ERR ret = 0;
3154 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003155 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003156 enum yang_keyword kw;
3157 struct lysp_grp *grp;
3158
3159 LYSP_ARRAY_NEW_RET(ctx, groupings, grp, LY_EMEM);
3160
3161 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003162 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003163 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003164
Radek Krejci44ceedc2018-10-02 15:54:31 +02003165 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003166
3167 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003168 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003169
3170 switch (kw) {
3171 case YANG_DESCRIPTION:
3172 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts);
3173 break;
3174 case YANG_REFERENCE:
3175 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts);
3176 break;
3177 case YANG_STATUS:
3178 ret = parse_status(ctx, data, &grp->flags, &grp->exts);
3179 break;
3180
3181 case YANG_ANYDATA:
3182 case YANG_ANYXML:
3183 ret = parse_any(ctx, data, kw, &grp->data);
3184 break;
3185 case YANG_CHOICE:
3186 ret = parse_choice(ctx, data, &grp->data);
3187 break;
3188 case YANG_CONTAINER:
3189 ret = parse_container(ctx, data, &grp->data);
3190 break;
3191 case YANG_LEAF:
3192 ret = parse_leaf(ctx, data, &grp->data);
3193 break;
3194 case YANG_LEAF_LIST:
3195 ret = parse_leaflist(ctx, data, &grp->data);
3196 break;
3197 case YANG_LIST:
3198 ret = parse_list(ctx, data, &grp->data);
3199 break;
3200 case YANG_USES:
3201 ret = parse_uses(ctx, data, &grp->data);
3202 break;
3203
3204 case YANG_TYPEDEF:
3205 ret = parse_typedef(ctx, data, &grp->typedefs);
3206 break;
3207 case YANG_ACTION:
3208 ret = parse_action(ctx, data, &grp->actions);
3209 break;
3210 case YANG_GROUPING:
3211 ret = parse_grouping(ctx, data, &grp->groupings);
3212 break;
3213 case YANG_NOTIFICATION:
3214 ret = parse_notif(ctx, data, &grp->notifs);
3215 break;
3216 case YANG_CUSTOM:
3217 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts);
3218 break;
3219 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003220 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003221 return LY_EVALID;
3222 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003223 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003225 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003226
3227 return ret;
3228}
3229
Michal Vaskoea5abea2018-09-18 13:10:54 +02003230/**
3231 * @brief Parse the refine statement.
3232 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003233 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003234 * @param[in,out] data Data to read from, always moved to currently handled character.
3235 * @param[in,out] augments Augments to add to.
3236 *
3237 * @return LY_ERR values.
3238 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003239static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003240parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003241{
3242 LY_ERR ret = 0;
3243 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003244 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003245 enum yang_keyword kw;
3246 struct lysp_augment *aug;
3247
3248 LYSP_ARRAY_NEW_RET(ctx, augments, aug, LY_EMEM);
3249
3250 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003251 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003252 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003253
Radek Krejci44ceedc2018-10-02 15:54:31 +02003254 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003255 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003256 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003257
3258 switch (kw) {
3259 case YANG_DESCRIPTION:
3260 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts);
3261 break;
3262 case YANG_IF_FEATURE:
3263 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts);
3264 break;
3265 case YANG_REFERENCE:
3266 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts);
3267 break;
3268 case YANG_STATUS:
3269 ret = parse_status(ctx, data, &aug->flags, &aug->exts);
3270 break;
3271 case YANG_WHEN:
3272 ret = parse_when(ctx, data, &aug->when);
3273 break;
3274
3275 case YANG_ANYDATA:
3276 case YANG_ANYXML:
3277 ret = parse_any(ctx, data, kw, &aug->child);
3278 break;
3279 case YANG_CASE:
3280 ret = parse_case(ctx, data, &aug->child);
3281 break;
3282 case YANG_CHOICE:
3283 ret = parse_choice(ctx, data, &aug->child);
3284 break;
3285 case YANG_CONTAINER:
3286 ret = parse_container(ctx, data, &aug->child);
3287 break;
3288 case YANG_LEAF:
3289 ret = parse_leaf(ctx, data, &aug->child);
3290 break;
3291 case YANG_LEAF_LIST:
3292 ret = parse_leaflist(ctx, data, &aug->child);
3293 break;
3294 case YANG_LIST:
3295 ret = parse_list(ctx, data, &aug->child);
3296 break;
3297 case YANG_USES:
3298 ret = parse_uses(ctx, data, &aug->child);
3299 break;
3300
3301 case YANG_ACTION:
3302 ret = parse_action(ctx, data, &aug->actions);
3303 break;
3304 case YANG_NOTIFICATION:
3305 ret = parse_notif(ctx, data, &aug->notifs);
3306 break;
3307 case YANG_CUSTOM:
3308 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts);
3309 break;
3310 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003311 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003312 return LY_EVALID;
3313 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003314 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003315 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003316 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003317
3318 return ret;
3319}
3320
Michal Vaskoea5abea2018-09-18 13:10:54 +02003321/**
3322 * @brief Parse the uses statement.
3323 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003324 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003325 * @param[in,out] data Data to read from, always moved to currently handled character.
3326 * @param[in,out] siblings Siblings to add to.
3327 *
3328 * @return LY_ERR values.
3329 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003330static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003331parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003332{
3333 LY_ERR ret = 0;
3334 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003335 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003336 enum yang_keyword kw;
3337 struct lysp_node *iter;
3338 struct lysp_node_uses *uses;
3339
3340 /* create structure */
3341 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003342 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003343 uses->nodetype = LYS_USES;
3344
3345 /* insert into siblings */
3346 if (!*siblings) {
3347 *siblings = (struct lysp_node *)uses;
3348 } else {
3349 for (iter = *siblings; iter->next; iter = iter->next);
3350 iter->next = (struct lysp_node *)uses;
3351 }
3352
3353 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003354 ret = get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003355 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003356
Radek Krejci44ceedc2018-10-02 15:54:31 +02003357 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003358
3359 /* parse substatements */
3360 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003361 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003362
3363 switch (kw) {
3364 case YANG_DESCRIPTION:
3365 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts);
3366 break;
3367 case YANG_IF_FEATURE:
3368 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts);
3369 break;
3370 case YANG_REFERENCE:
3371 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts);
3372 break;
3373 case YANG_STATUS:
3374 ret = parse_status(ctx, data, &uses->flags, &uses->exts);
3375 break;
3376 case YANG_WHEN:
3377 ret = parse_when(ctx, data, &uses->when);
3378 break;
3379
3380 case YANG_REFINE:
3381 ret = parse_refine(ctx, data, &uses->refines);
3382 break;
3383 case YANG_AUGMENT:
3384 ret = parse_augment(ctx, data, &uses->augments);
3385 break;
3386 case YANG_CUSTOM:
3387 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts);
3388 break;
3389 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003390 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003391 return LY_EVALID;
3392 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003393 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003394 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003395 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003396
3397 return ret;
3398}
3399
Michal Vaskoea5abea2018-09-18 13:10:54 +02003400/**
3401 * @brief Parse the case statement.
3402 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003403 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003404 * @param[in,out] data Data to read from, always moved to currently handled character.
3405 * @param[in,out] siblings Siblings to add to.
3406 *
3407 * @return LY_ERR values.
3408 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003409static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003410parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003411{
3412 LY_ERR ret = 0;
3413 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003414 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003415 enum yang_keyword kw;
3416 struct lysp_node *iter;
3417 struct lysp_node_case *cas;
3418
3419 /* create structure */
3420 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003421 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003422 cas->nodetype = LYS_CASE;
3423
3424 /* insert into siblings */
3425 if (!*siblings) {
3426 *siblings = (struct lysp_node *)cas;
3427 } else {
3428 for (iter = *siblings; iter->next; iter = iter->next);
3429 iter->next = (struct lysp_node *)cas;
3430 }
3431
3432 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003433 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003434 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003435
Radek Krejci44ceedc2018-10-02 15:54:31 +02003436 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003437
3438 /* parse substatements */
3439 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003440 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003441
3442 switch (kw) {
3443 case YANG_DESCRIPTION:
3444 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts);
3445 break;
3446 case YANG_IF_FEATURE:
3447 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts);
3448 break;
3449 case YANG_REFERENCE:
3450 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts);
3451 break;
3452 case YANG_STATUS:
3453 ret = parse_status(ctx, data, &cas->flags, &cas->exts);
3454 break;
3455 case YANG_WHEN:
3456 ret = parse_when(ctx, data, &cas->when);
3457 break;
3458
3459 case YANG_ANYDATA:
3460 case YANG_ANYXML:
3461 ret = parse_any(ctx, data, kw, &cas->child);
3462 break;
3463 case YANG_CHOICE:
3464 ret = parse_case(ctx, data, &cas->child);
3465 break;
3466 case YANG_CONTAINER:
3467 ret = parse_container(ctx, data, &cas->child);
3468 break;
3469 case YANG_LEAF:
3470 ret = parse_leaf(ctx, data, &cas->child);
3471 break;
3472 case YANG_LEAF_LIST:
3473 ret = parse_leaflist(ctx, data, &cas->child);
3474 break;
3475 case YANG_LIST:
3476 ret = parse_list(ctx, data, &cas->child);
3477 break;
3478 case YANG_USES:
3479 ret = parse_uses(ctx, data, &cas->child);
3480 break;
3481 case YANG_CUSTOM:
3482 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts);
3483 break;
3484 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003485 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003486 return LY_EVALID;
3487 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003488 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003489 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003490 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003491
3492 return ret;
3493}
3494
Michal Vaskoea5abea2018-09-18 13:10:54 +02003495/**
3496 * @brief Parse the choice statement.
3497 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003498 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003499 * @param[in,out] data Data to read from, always moved to currently handled character.
3500 * @param[in,out] siblings Siblings to add to.
3501 *
3502 * @return LY_ERR values.
3503 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003504static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003505parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003506{
3507 LY_ERR ret = 0;
3508 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003509 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003510 enum yang_keyword kw;
3511 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003512 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003513
3514 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003515 choice = calloc(1, sizeof *choice);
3516 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3517 choice->nodetype = LYS_CHOICE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003518
3519 /* insert into siblings */
3520 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003521 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003522 } else {
3523 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003524 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003525 }
3526
3527 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003528 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003529 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003530
Radek Krejci44ceedc2018-10-02 15:54:31 +02003531 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003532
3533 /* parse substatements */
3534 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003535 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003536
3537 switch (kw) {
3538 case YANG_CONFIG:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003539 ret = parse_config(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003540 break;
3541 case YANG_DESCRIPTION:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003542 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543 break;
3544 case YANG_IF_FEATURE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003545 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003546 break;
3547 case YANG_MANDATORY:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003548 ret = parse_mandatory(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003549 break;
3550 case YANG_REFERENCE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003551 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003552 break;
3553 case YANG_STATUS:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003554 ret = parse_status(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003555 break;
3556 case YANG_WHEN:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003557 ret = parse_when(ctx, data, &choice->when);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003558 break;
3559 case YANG_DEFAULT:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003560 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_IDENTIF_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003561 break;
3562
3563 case YANG_ANYDATA:
3564 case YANG_ANYXML:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003565 ret = parse_any(ctx, data, kw, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003566 break;
3567 case YANG_CASE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003568 ret = parse_case(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569 break;
3570 case YANG_CHOICE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003571 ret = parse_choice(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003572 break;
3573 case YANG_CONTAINER:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003574 ret = parse_container(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003575 break;
3576 case YANG_LEAF:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003577 ret = parse_leaf(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003578 break;
3579 case YANG_LEAF_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003580 ret = parse_leaflist(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003581 break;
3582 case YANG_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003583 ret = parse_list(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584 break;
3585 case YANG_CUSTOM:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003586 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003587 break;
3588 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003589 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590 return LY_EVALID;
3591 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003592 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003593 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003594 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003595
3596 return ret;
3597}
3598
Michal Vaskoea5abea2018-09-18 13:10:54 +02003599/**
3600 * @brief Parse the container statement.
3601 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003602 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003603 * @param[in,out] data Data to read from, always moved to currently handled character.
3604 * @param[in,out] siblings Siblings to add to.
3605 *
3606 * @return LY_ERR values.
3607 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003608static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003609parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003610{
3611 LY_ERR ret = 0;
3612 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003613 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003614 enum yang_keyword kw;
3615 struct lysp_node *iter;
3616 struct lysp_node_container *cont;
3617
3618 /* create structure */
3619 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003620 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003621 cont->nodetype = LYS_CONTAINER;
3622
3623 /* insert into siblings */
3624 if (!*siblings) {
3625 *siblings = (struct lysp_node *)cont;
3626 } else {
3627 for (iter = *siblings; iter->next; iter = iter->next);
3628 iter->next = (struct lysp_node *)cont;
3629 }
3630
3631 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003632 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003633 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003634
Radek Krejci44ceedc2018-10-02 15:54:31 +02003635 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003636
3637 /* parse substatements */
3638 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003639 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003640
3641 switch (kw) {
3642 case YANG_CONFIG:
3643 ret = parse_config(ctx, data, &cont->flags, &cont->exts);
3644 break;
3645 case YANG_DESCRIPTION:
3646 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts);
3647 break;
3648 case YANG_IF_FEATURE:
3649 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts);
3650 break;
3651 case YANG_REFERENCE:
3652 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts);
3653 break;
3654 case YANG_STATUS:
3655 ret = parse_status(ctx, data, &cont->flags, &cont->exts);
3656 break;
3657 case YANG_WHEN:
3658 ret = parse_when(ctx, data, &cont->when);
3659 break;
3660 case YANG_PRESENCE:
3661 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts);
3662 break;
3663
3664 case YANG_ANYDATA:
3665 case YANG_ANYXML:
3666 ret = parse_any(ctx, data, kw, &cont->child);
3667 break;
3668 case YANG_CHOICE:
3669 ret = parse_choice(ctx, data, &cont->child);
3670 break;
3671 case YANG_CONTAINER:
3672 ret = parse_container(ctx, data, &cont->child);
3673 break;
3674 case YANG_LEAF:
3675 ret = parse_leaf(ctx, data, &cont->child);
3676 break;
3677 case YANG_LEAF_LIST:
3678 ret = parse_leaflist(ctx, data, &cont->child);
3679 break;
3680 case YANG_LIST:
3681 ret = parse_list(ctx, data, &cont->child);
3682 break;
3683 case YANG_USES:
3684 ret = parse_uses(ctx, data, &cont->child);
3685 break;
3686
3687 case YANG_TYPEDEF:
3688 ret = parse_typedef(ctx, data, &cont->typedefs);
3689 break;
3690 case YANG_MUST:
3691 ret = parse_restrs(ctx, data, kw, &cont->musts);
3692 break;
3693 case YANG_ACTION:
3694 ret = parse_action(ctx, data, &cont->actions);
3695 break;
3696 case YANG_GROUPING:
3697 ret = parse_grouping(ctx, data, &cont->groupings);
3698 break;
3699 case YANG_NOTIFICATION:
3700 ret = parse_notif(ctx, data, &cont->notifs);
3701 break;
3702 case YANG_CUSTOM:
3703 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts);
3704 break;
3705 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003706 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003707 return LY_EVALID;
3708 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003709 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003710 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003711 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003712
3713 return ret;
3714}
3715
Michal Vaskoea5abea2018-09-18 13:10:54 +02003716/**
3717 * @brief Parse the list statement.
3718 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003719 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003720 * @param[in,out] data Data to read from, always moved to currently handled character.
3721 * @param[in,out] siblings Siblings to add to.
3722 *
3723 * @return LY_ERR values.
3724 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003726parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003727{
3728 LY_ERR ret = 0;
3729 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003730 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003731 enum yang_keyword kw;
3732 struct lysp_node *iter;
3733 struct lysp_node_list *list;
3734
3735 /* create structure */
3736 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003737 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003738 list->nodetype = LYS_LIST;
3739
3740 /* insert into siblings */
3741 if (!*siblings) {
3742 *siblings = (struct lysp_node *)list;
3743 } else {
3744 for (iter = *siblings; iter->next; iter = iter->next);
3745 iter->next = (struct lysp_node *)list;
3746 }
3747
3748 /* get name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003749 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003750 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003751
Radek Krejci44ceedc2018-10-02 15:54:31 +02003752 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003753
3754 /* parse substatements */
3755 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003756 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003757
3758 switch (kw) {
3759 case YANG_CONFIG:
3760 ret = parse_config(ctx, data, &list->flags, &list->exts);
3761 break;
3762 case YANG_DESCRIPTION:
3763 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts);
3764 break;
3765 case YANG_IF_FEATURE:
3766 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts);
3767 break;
3768 case YANG_REFERENCE:
3769 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts);
3770 break;
3771 case YANG_STATUS:
3772 ret = parse_status(ctx, data, &list->flags, &list->exts);
3773 break;
3774 case YANG_WHEN:
3775 ret = parse_when(ctx, data, &list->when);
3776 break;
3777 case YANG_KEY:
3778 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts);
3779 break;
3780 case YANG_MAX_ELEMENTS:
3781 ret = parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts);
3782 break;
3783 case YANG_MIN_ELEMENTS:
3784 ret = parse_minelements(ctx, data, &list->min, &list->flags, &list->exts);
3785 break;
3786 case YANG_ORDERED_BY:
3787 ret = parse_orderedby(ctx, data, &list->flags, &list->exts);
3788 break;
3789 case YANG_UNIQUE:
3790 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts);
3791 break;
3792
3793 case YANG_ANYDATA:
3794 case YANG_ANYXML:
3795 ret = parse_any(ctx, data, kw, &list->child);
3796 break;
3797 case YANG_CHOICE:
3798 ret = parse_choice(ctx, data, &list->child);
3799 break;
3800 case YANG_CONTAINER:
3801 ret = parse_container(ctx, data, &list->child);
3802 break;
3803 case YANG_LEAF:
3804 ret = parse_leaf(ctx, data, &list->child);
3805 break;
3806 case YANG_LEAF_LIST:
3807 ret = parse_leaflist(ctx, data, &list->child);
3808 break;
3809 case YANG_LIST:
3810 ret = parse_list(ctx, data, &list->child);
3811 break;
3812 case YANG_USES:
3813 ret = parse_uses(ctx, data, &list->child);
3814 break;
3815
3816 case YANG_TYPEDEF:
3817 ret = parse_typedef(ctx, data, &list->typedefs);
3818 break;
3819 case YANG_MUST:
3820 ret = parse_restrs(ctx, data, kw, &list->musts);
3821 break;
3822 case YANG_ACTION:
3823 ret = parse_action(ctx, data, &list->actions);
3824 break;
3825 case YANG_GROUPING:
3826 ret = parse_grouping(ctx, data, &list->groupings);
3827 break;
3828 case YANG_NOTIFICATION:
3829 ret = parse_notif(ctx, data, &list->notifs);
3830 break;
3831 case YANG_CUSTOM:
3832 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts);
3833 break;
3834 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003835 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003836 return LY_EVALID;
3837 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003838 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003839 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003840 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003841
3842 return ret;
3843}
3844
Michal Vaskoea5abea2018-09-18 13:10:54 +02003845/**
3846 * @brief Parse the yin-element statement.
3847 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003848 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003849 * @param[in,out] data Data to read from, always moved to currently handled character.
3850 * @param[in,out] flags Flags to write to.
3851 * @param[in,out] exts Extension instances to add to.
3852 *
3853 * @return LY_ERR values.
3854 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003855static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003856parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003857{
3858 LY_ERR ret = 0;
3859 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003860 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003861 enum yang_keyword kw;
3862
3863 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003864 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003865 return LY_EVALID;
3866 }
3867
3868 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003869 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003870 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003871
3872 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3873 *flags |= LYS_YINELEM_TRUE;
3874 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3875 *flags |= LYS_YINELEM_FALSE;
3876 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003877 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003878 free(buf);
3879 return LY_EVALID;
3880 }
3881 free(buf);
3882
3883 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003884 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003885
3886 switch (kw) {
3887 case YANG_CUSTOM:
3888 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02003889 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003890 break;
3891 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003892 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003893 return LY_EVALID;
3894 }
3895 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003896 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003897
3898 return ret;
3899}
3900
Michal Vaskoea5abea2018-09-18 13:10:54 +02003901/**
3902 * @brief Parse the yin-element statement.
3903 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003904 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003905 * @param[in,out] data Data to read from, always moved to currently handled character.
3906 * @param[in,out] argument Value to write to.
3907 * @param[in,out] flags Flags to write to.
3908 * @param[in,out] exts Extension instances to add to.
3909 *
3910 * @return LY_ERR values.
3911 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003912static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003913parse_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 +02003914{
3915 LY_ERR ret = 0;
3916 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003917 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003918 enum yang_keyword kw;
3919
3920 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003921 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003922 return LY_EVALID;
3923 }
3924
3925 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003926 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003927 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003928
Radek Krejci44ceedc2018-10-02 15:54:31 +02003929 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003930 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003931 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003932
3933 switch (kw) {
3934 case YANG_YIN_ELEMENT:
3935 ret = parse_yinelement(ctx, data, flags, exts);
3936 break;
3937 case YANG_CUSTOM:
3938 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts);
3939 break;
3940 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003941 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003942 return LY_EVALID;
3943 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003944 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003945 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003946 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003947
3948 return ret;
3949}
3950
Michal Vaskoea5abea2018-09-18 13:10:54 +02003951/**
3952 * @brief Parse the extension statement.
3953 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003954 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003955 * @param[in,out] data Data to read from, always moved to currently handled character.
3956 * @param[in,out] extensions Extensions to add to.
3957 *
3958 * @return LY_ERR values.
3959 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003960static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003961parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003962{
3963 LY_ERR ret = 0;
3964 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003965 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003966 enum yang_keyword kw;
3967 struct lysp_ext *ex;
3968
3969 LYSP_ARRAY_NEW_RET(ctx, extensions, ex, LY_EMEM);
3970
3971 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02003972 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003973 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003974
Radek Krejci44ceedc2018-10-02 15:54:31 +02003975 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003976 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003977 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003978
3979 switch (kw) {
3980 case YANG_DESCRIPTION:
3981 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts);
3982 break;
3983 case YANG_REFERENCE:
3984 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts);
3985 break;
3986 case YANG_STATUS:
3987 ret = parse_status(ctx, data, &ex->flags, &ex->exts);
3988 break;
3989 case YANG_ARGUMENT:
3990 ret = parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts);
3991 break;
3992 case YANG_CUSTOM:
3993 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts);
3994 break;
3995 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003996 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003997 return LY_EVALID;
3998 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003999 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004000 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004001 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004002
4003 return ret;
4004}
4005
Michal Vaskoea5abea2018-09-18 13:10:54 +02004006/**
4007 * @brief Parse the deviate statement.
4008 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004009 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004010 * @param[in,out] data Data to read from, always moved to currently handled character.
4011 * @param[in,out] deviates Deviates to add to.
4012 *
4013 * @return LY_ERR values.
4014 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004015static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004016parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017{
4018 LY_ERR ret = 0;
4019 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004020 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004021 enum yang_keyword kw;
4022 struct lysp_deviate *iter, *d;
4023 struct lysp_deviate_add *d_add = NULL;
4024 struct lysp_deviate_rpl *d_rpl = NULL;
4025 struct lysp_deviate_del *d_del = NULL;
4026 const char **d_units, ***d_uniques, ***d_dflts;
4027 struct lysp_restr **d_musts;
4028 uint16_t *d_flags;
4029 uint32_t *d_min, *d_max;
4030
4031 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004032 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004033 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004034
4035 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4036 dev_mod = LYS_DEV_NOT_SUPPORTED;
4037 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4038 dev_mod = LYS_DEV_ADD;
4039 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4040 dev_mod = LYS_DEV_REPLACE;
4041 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4042 dev_mod = LYS_DEV_DELETE;
4043 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004044 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004045 free(buf);
4046 return LY_EVALID;
4047 }
4048 free(buf);
4049
4050 /* create structure */
4051 switch (dev_mod) {
4052 case LYS_DEV_NOT_SUPPORTED:
4053 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004054 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004055 break;
4056 case LYS_DEV_ADD:
4057 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004058 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004059 d = (struct lysp_deviate *)d_add;
4060 d_units = &d_add->units;
4061 d_uniques = &d_add->uniques;
4062 d_dflts = &d_add->dflts;
4063 d_musts = &d_add->musts;
4064 d_flags = &d_add->flags;
4065 d_min = &d_add->min;
4066 d_max = &d_add->max;
4067 break;
4068 case LYS_DEV_REPLACE:
4069 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004070 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004071 d = (struct lysp_deviate *)d_rpl;
4072 d_units = &d_rpl->units;
4073 d_flags = &d_rpl->flags;
4074 d_min = &d_rpl->min;
4075 d_max = &d_rpl->max;
4076 break;
4077 case LYS_DEV_DELETE:
4078 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004079 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004080 d = (struct lysp_deviate *)d_del;
4081 d_units = &d_del->units;
4082 d_uniques = &d_del->uniques;
4083 d_dflts = &d_del->dflts;
4084 d_musts = &d_del->musts;
4085 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004086 break;
4087 default:
4088 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004089 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004090 }
4091 d->mod = dev_mod;
4092
4093 /* insert into siblings */
4094 if (!*deviates) {
4095 *deviates = d;
4096 } else {
4097 for (iter = *deviates; iter->next; iter = iter->next);
4098 iter->next = d;
4099 }
4100
4101 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004102 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004103
4104 switch (kw) {
4105 case YANG_CONFIG:
4106 switch (dev_mod) {
4107 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004108 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004109 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004110 return LY_EVALID;
4111 default:
4112 ret = parse_config(ctx, data, d_flags, &d->exts);
4113 break;
4114 }
4115 break;
4116 case YANG_DEFAULT:
4117 switch (dev_mod) {
4118 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004119 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004120 return LY_EVALID;
4121 case LYS_DEV_REPLACE:
4122 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts);
4123 break;
4124 default:
4125 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts);
4126 break;
4127 }
4128 break;
4129 case YANG_MANDATORY:
4130 switch (dev_mod) {
4131 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004132 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004133 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004134 return LY_EVALID;
4135 default:
4136 ret = parse_mandatory(ctx, data, d_flags, &d->exts);
4137 break;
4138 }
4139 break;
4140 case YANG_MAX_ELEMENTS:
4141 switch (dev_mod) {
4142 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004143 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004144 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004145 return LY_EVALID;
4146 default:
4147 ret = parse_maxelements(ctx, data, d_max, d_flags, &d->exts);
4148 break;
4149 }
4150 break;
4151 case YANG_MIN_ELEMENTS:
4152 switch (dev_mod) {
4153 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004154 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004155 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004156 return LY_EVALID;
4157 default:
4158 ret = parse_minelements(ctx, data, d_min, d_flags, &d->exts);
4159 break;
4160 }
4161 break;
4162 case YANG_MUST:
4163 switch (dev_mod) {
4164 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004165 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004166 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004167 return LY_EVALID;
4168 default:
4169 ret = parse_restrs(ctx, data, kw, d_musts);
4170 break;
4171 }
4172 break;
4173 case YANG_TYPE:
4174 switch (dev_mod) {
4175 case LYS_DEV_NOT_SUPPORTED:
4176 case LYS_DEV_ADD:
4177 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004178 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179 return LY_EVALID;
4180 default:
4181 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004182 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004183 ret = parse_type(ctx, data, d_rpl->type);
4184 break;
4185 }
4186 break;
4187 case YANG_UNIQUE:
4188 switch (dev_mod) {
4189 case LYS_DEV_NOT_SUPPORTED:
4190 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004191 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004192 return LY_EVALID;
4193 default:
4194 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts);
4195 break;
4196 }
4197 break;
4198 case YANG_UNITS:
4199 switch (dev_mod) {
4200 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004201 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004202 return LY_EVALID;
4203 default:
4204 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts);
4205 break;
4206 }
4207 break;
4208 case YANG_CUSTOM:
4209 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts);
4210 break;
4211 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004212 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004213 return LY_EVALID;
4214 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004215 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004216 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004217 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004218
4219 return ret;
4220}
4221
Michal Vaskoea5abea2018-09-18 13:10:54 +02004222/**
4223 * @brief Parse the deviation statement.
4224 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004225 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004226 * @param[in,out] data Data to read from, always moved to currently handled character.
4227 * @param[in,out] deviations Deviations to add to.
4228 *
4229 * @return LY_ERR values.
4230 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004231static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004232parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004233{
4234 LY_ERR ret = 0;
4235 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004236 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004237 enum yang_keyword kw;
4238 struct lysp_deviation *dev;
4239
4240 LYSP_ARRAY_NEW_RET(ctx, deviations, dev, LY_EMEM);
4241
4242 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004243 ret = get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004244 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004245
Radek Krejci44ceedc2018-10-02 15:54:31 +02004246 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004247 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004248 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004249
4250 switch (kw) {
4251 case YANG_DESCRIPTION:
4252 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts);
4253 break;
4254 case YANG_DEVIATE:
4255 ret = parse_deviate(ctx, data, &dev->deviates);
4256 break;
4257 case YANG_REFERENCE:
4258 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts);
4259 break;
4260 case YANG_CUSTOM:
4261 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts);
4262 break;
4263 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004264 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004265 return LY_EVALID;
4266 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004267 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004268 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004269 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004270
4271 /* mandatory substatements */
4272 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004273 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004274 return LY_EVALID;
4275 }
4276
4277 return ret;
4278}
4279
Michal Vaskoea5abea2018-09-18 13:10:54 +02004280/**
4281 * @brief Parse the feature statement.
4282 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004283 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004284 * @param[in,out] data Data to read from, always moved to currently handled character.
4285 * @param[in,out] features Features to add to.
4286 *
4287 * @return LY_ERR values.
4288 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004289static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004290parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004291{
4292 LY_ERR ret = 0;
4293 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004294 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004295 enum yang_keyword kw;
4296 struct lysp_feature *feat;
4297
4298 LYSP_ARRAY_NEW_RET(ctx, features, feat, LY_EMEM);
4299
4300 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004301 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004302 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004303
Radek Krejci44ceedc2018-10-02 15:54:31 +02004304 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004305 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004306 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004307
4308 switch (kw) {
4309 case YANG_DESCRIPTION:
4310 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts);
4311 break;
4312 case YANG_IF_FEATURE:
4313 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts);
4314 break;
4315 case YANG_REFERENCE:
4316 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts);
4317 break;
4318 case YANG_STATUS:
4319 ret = parse_status(ctx, data, &feat->flags, &feat->exts);
4320 break;
4321 case YANG_CUSTOM:
4322 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts);
4323 break;
4324 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004325 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004326 return LY_EMEM;
4327 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004328 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004329 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004330 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004331
4332 return ret;
4333}
4334
Michal Vaskoea5abea2018-09-18 13:10:54 +02004335/**
4336 * @brief Parse the identity statement.
4337 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004338 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004339 * @param[in,out] data Data to read from, always moved to currently handled character.
4340 * @param[in,out] identities Identities to add to.
4341 *
4342 * @return LY_ERR values.
4343 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004344static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004345parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004346{
4347 LY_ERR ret = 0;
4348 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004349 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004350 enum yang_keyword kw;
4351 struct lysp_ident *ident;
4352
4353 LYSP_ARRAY_NEW_RET(ctx, identities, ident, LY_EMEM);
4354
4355 /* get value */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004356 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004357 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004358
Radek Krejci44ceedc2018-10-02 15:54:31 +02004359 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004360 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004361 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004362
4363 switch (kw) {
4364 case YANG_DESCRIPTION:
4365 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts);
4366 break;
4367 case YANG_IF_FEATURE:
4368 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts);
4369 break;
4370 case YANG_REFERENCE:
4371 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts);
4372 break;
4373 case YANG_STATUS:
4374 ret = parse_status(ctx, data, &ident->flags, &ident->exts);
4375 break;
4376 case YANG_BASE:
4377 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts);
4378 break;
4379 case YANG_CUSTOM:
4380 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts);
4381 break;
4382 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004383 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004384 return LY_EVALID;
4385 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004386 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004387 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004388 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004389
4390 return ret;
4391}
4392
Michal Vaskoea5abea2018-09-18 13:10:54 +02004393/**
4394 * @brief Parse the module or submodule statement.
4395 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004396 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004397 * @param[in,out] data Data to read from, always moved to currently handled character.
4398 * @param[in,out] mod Module to write to.
4399 *
4400 * @return LY_ERR values.
4401 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004402static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004403parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004404{
4405 LY_ERR ret = 0;
4406 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004407 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004408 enum yang_keyword kw, prev_kw = 0;
4409 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4410
4411 /* (sub)module name */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004412 ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004413 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004414
Radek Krejci44ceedc2018-10-02 15:54:31 +02004415 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004416 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004417 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004418
4419 switch (kw) {
4420 /* module header */
4421 case YANG_NAMESPACE:
4422 case YANG_PREFIX:
4423 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004424 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004425 return LY_EVALID;
4426 }
4427 /* fallthrough */
4428 case YANG_BELONGS_TO:
4429 if ((kw == YANG_BELONGS_TO) && !mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004430 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004431 return LY_EVALID;
4432 }
4433 /* fallthrough */
4434 case YANG_YANG_VERSION:
4435 if (mod_stmt > Y_MOD_MODULE_HEADER) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004436 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004437 return LY_EVALID;
4438 }
4439 break;
4440 /* linkage */
4441 case YANG_INCLUDE:
4442 case YANG_IMPORT:
4443 if (mod_stmt > Y_MOD_LINKAGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004444 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004445 return LY_EVALID;
4446 }
4447 mod_stmt = Y_MOD_LINKAGE;
4448 break;
4449 /* meta */
4450 case YANG_ORGANIZATION:
4451 case YANG_CONTACT:
4452 case YANG_DESCRIPTION:
4453 case YANG_REFERENCE:
4454 if (mod_stmt > Y_MOD_META) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004455 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004456 return LY_EVALID;
4457 }
4458 mod_stmt = Y_MOD_META;
4459 break;
4460
4461 /* revision */
4462 case YANG_REVISION:
4463 if (mod_stmt > Y_MOD_REVISION) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004464 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004465 return LY_EVALID;
4466 }
4467 mod_stmt = Y_MOD_REVISION;
4468 break;
4469
4470 /* body */
4471 case YANG_ANYDATA:
4472 case YANG_ANYXML:
4473 case YANG_AUGMENT:
4474 case YANG_CHOICE:
4475 case YANG_CONTAINER:
4476 case YANG_DEVIATION:
4477 case YANG_EXTENSION:
4478 case YANG_FEATURE:
4479 case YANG_GROUPING:
4480 case YANG_IDENTITY:
4481 case YANG_LEAF:
4482 case YANG_LEAF_LIST:
4483 case YANG_LIST:
4484 case YANG_NOTIFICATION:
4485 case YANG_RPC:
4486 case YANG_TYPEDEF:
4487 case YANG_USES:
4488 case YANG_CUSTOM:
4489 mod_stmt = Y_MOD_BODY;
4490 break;
4491 default:
4492 /* error handled in the next switch */
4493 break;
4494 }
4495 prev_kw = kw;
4496
4497 switch (kw) {
4498 /* module header */
4499 case YANG_YANG_VERSION:
4500 ret = parse_yangversion(ctx, data, mod);
4501 break;
4502 case YANG_NAMESPACE:
4503 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->ns, Y_STR_ARG, &mod->exts);
4504 break;
4505 case YANG_PREFIX:
4506 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts);
4507 break;
4508 case YANG_BELONGS_TO:
4509 ret = parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts);
4510 break;
4511
4512 /* linkage */
4513 case YANG_INCLUDE:
4514 ret = parse_include(ctx, data, &mod->includes);
4515 break;
4516 case YANG_IMPORT:
4517 ret = parse_import(ctx, data, &mod->imports);
4518 break;
4519
4520 /* meta */
4521 case YANG_ORGANIZATION:
4522 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->org, Y_STR_ARG, &mod->exts);
4523 break;
4524 case YANG_CONTACT:
4525 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->contact, Y_STR_ARG, &mod->exts);
4526 break;
4527 case YANG_DESCRIPTION:
4528 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->dsc, Y_STR_ARG, &mod->exts);
4529 break;
4530 case YANG_REFERENCE:
4531 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->ref, Y_STR_ARG, &mod->exts);
4532 break;
4533
4534 /* revision */
4535 case YANG_REVISION:
4536 ret = parse_revision(ctx, data, &mod->revs);
4537 break;
4538
4539 /* body */
4540 case YANG_ANYDATA:
4541 case YANG_ANYXML:
4542 ret = parse_any(ctx, data, kw, &mod->data);
4543 break;
4544 case YANG_CHOICE:
4545 ret = parse_choice(ctx, data, &mod->data);
4546 break;
4547 case YANG_CONTAINER:
4548 ret = parse_container(ctx, data, &mod->data);
4549 break;
4550 case YANG_LEAF:
4551 ret = parse_leaf(ctx, data, &mod->data);
4552 break;
4553 case YANG_LEAF_LIST:
4554 ret = parse_leaflist(ctx, data, &mod->data);
4555 break;
4556 case YANG_LIST:
4557 ret = parse_list(ctx, data, &mod->data);
4558 break;
4559 case YANG_USES:
4560 ret = parse_uses(ctx, data, &mod->data);
4561 break;
4562
4563 case YANG_AUGMENT:
4564 ret = parse_augment(ctx, data, &mod->augments);
4565 break;
4566 case YANG_DEVIATION:
4567 ret = parse_deviation(ctx, data, &mod->deviations);
4568 break;
4569 case YANG_EXTENSION:
4570 ret = parse_extension(ctx, data, &mod->extensions);
4571 break;
4572 case YANG_FEATURE:
4573 ret = parse_feature(ctx, data, &mod->features);
4574 break;
4575 case YANG_GROUPING:
4576 ret = parse_grouping(ctx, data, &mod->groupings);
4577 break;
4578 case YANG_IDENTITY:
4579 ret = parse_identity(ctx, data, &mod->identities);
4580 break;
4581 case YANG_NOTIFICATION:
4582 ret = parse_notif(ctx, data, &mod->notifs);
4583 break;
4584 case YANG_RPC:
4585 ret = parse_action(ctx, data, &mod->rpcs);
4586 break;
4587 case YANG_TYPEDEF:
4588 ret = parse_typedef(ctx, data, &mod->typedefs);
4589 break;
4590 case YANG_CUSTOM:
4591 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts);
4592 break;
4593
4594 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004595 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004596 return LY_EVALID;
4597 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004598 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004599 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004600 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004601
4602 /* mandatory substatements */
4603 if (mod->submodule) {
4604 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004605 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004606 return LY_EVALID;
4607 }
4608 } else {
4609 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004610 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004611 return LY_EVALID;
4612 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004613 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004614 return LY_EVALID;
4615 }
4616 }
4617
4618 return ret;
4619}
4620
Radek Krejcid4557c62018-09-17 11:42:09 +02004621LY_ERR
Michal Vasko7fbc8162018-09-17 10:35:16 +02004622yang_parse(struct ly_ctx *ctx, const char *data, struct lysp_module **mod_p)
4623{
4624 LY_ERR ret = 0;
4625 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004626 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004627 enum yang_keyword kw;
4628 struct lysp_module *mod;
Radek Krejci44ceedc2018-10-02 15:54:31 +02004629 struct ly_parser_ctx context;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004630
Radek Krejci44ceedc2018-10-02 15:54:31 +02004631 context.ctx = ctx;
4632 context.line = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004633
4634 /* "module"/"submodule" */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004635 ret = get_keyword(&context, &data, &kw, &word, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004636 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004637
4638 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004639 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004640 ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004641 goto error;
4642 }
4643
4644 mod = calloc(1, sizeof *mod);
4645 LY_CHECK_ERR_GOTO(!mod, LOGMEM(ctx), error);
4646 if (kw == YANG_SUBMODULE) {
4647 mod->submodule = 1;
4648 }
4649
4650 /* substatements */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004651 ret = parse_sub_module(&context, &data, mod);
Radek Krejcic59bc972018-09-17 16:13:06 +02004652 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004653
4654 /* read some trailing spaces or new lines */
Radek Krejcifc62d7e2018-10-11 12:56:42 +02004655 ret = get_argument(&context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004656 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004657
4658 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004659 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004660 word_len, word);
4661 free(buf);
4662 goto error;
4663 }
4664 assert(!buf);
4665
4666 *mod_p = mod;
4667 return ret;
4668
4669error:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004670 /* TODO free module */
4671 return ret;
4672}