blob: 4c811f4cbffa5660bcac50689f69d83b87bd5f24 [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;
33 uint64_t line;
34};
35
36/* Macro to check YANG's yang-char grammar rule */
37#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
38 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
39 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
40 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
41 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
42 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
43 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
44 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
45 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
46 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
47
48/* These 2 macros checks YANG's identifier grammar rule */
49#define is_yangidentstartchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
50#define is_yangidentchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || \
51 c == '_' || c == '-' || c == '.')
52
53#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);} \
54 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
55
56#define LOGVAL_YANG(CTX, ...) LOGVAL((CTX)->ctx, LY_VLOG_LINE, &(CTX)->line, __VA_ARGS__)
57
Michal Vaskoea5abea2018-09-18 13:10:54 +020058/**
59 * @brief Loop through all substatements providing, return if there are none.
60 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020061 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020062 * @param[in] DATA Raw data to read from.
63 * @param[out] KW YANG keyword read.
64 * @param[out] WORD Pointer to the keyword itself.
65 * @param[out] WORD_LEN Length of the keyword.
66 * @param[out] ERR Variable for error storing.
67 *
68 * @return In case there are no substatements or a fatal error encountered.
69 */
Michal Vasko7fbc8162018-09-17 10:35:16 +020070#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR) \
71 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
Radek Krejcic59bc972018-09-17 16:13:06 +020072 LY_CHECK_RET(ERR); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020073 \
74 if (KW == YANG_SEMICOLON) { \
75 return ERR; \
76 } \
77 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +020078 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020079 return LY_EVALID; \
80 } \
81 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
82 !ERR && (KW != YANG_RIGHT_BRACE); \
83 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
84
Radek Krejci44ceedc2018-10-02 15:54:31 +020085static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
86static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
87static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
88static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
89static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings);
90static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +020091
Michal Vaskoea5abea2018-09-18 13:10:54 +020092/**
93 * @brief Add another character to dynamic buffer, a low-level function.
94 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020095 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +020096 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020097 * @param[in] ctx yang parser context for logging.
98 * @param[in, out] input Input string to process.
99 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200100 * @param[in,out] buf Buffer to use, can be moved by realloc().
101 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200102 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200103 *
104 * @return LY_ERR values.
105 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200106static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200107buf_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 +0200108{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200109 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200110 *buf_len += 16;
111 *buf = ly_realloc(*buf, *buf_len);
112 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
113 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200114 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200115
Radek Krejci44ceedc2018-10-02 15:54:31 +0200116 (*buf_used) += len;
117 (*input) += len;
118
Michal Vasko7fbc8162018-09-17 10:35:16 +0200119 return LY_SUCCESS;
120}
121
Michal Vaskoea5abea2018-09-18 13:10:54 +0200122/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200123 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200124 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200125 * @param[in] ctx yang parser context for logging.
126 * @param[in] c UTF8 code point of a character to check.
127 * @return LY_ERR values.
128 */
129static LY_ERR
130check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
131{
132 if (!is_yangutf8char(c)) {
133 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
134 return LY_EVALID;
135 }
136 return LY_SUCCESS;
137}
138
139/**
140 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
141 *
142 * @param[in] ctx yang parser context for logging.
143 * @param[in] c UTF8 code point of a character to check.
144 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
145 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers.
146 * If the identifier cannot be prefixed, NULL is expected.
147 * @return LY_ERR values.
148 */
149static LY_ERR
150check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
151{
152 if (first || (prefix && (*prefix) == 1)) {
153 if (!is_yangidentstartchar(c)) {
154 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
155 return LY_EVALID;
156 }
157 if (first) {
158 (*prefix) = 0;
159 } else {
160 (*prefix) = 2;
161 }
162 } else if (c == ':' && prefix && (*prefix) == 0) {
163 (*prefix) = 1;
164 } else if (!is_yangidentchar(c)) {
165 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
166 return LY_EVALID;
167 }
168
169 return LY_SUCCESS;
170}
171
172/**
173 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
174 *
175 * @param[in] ctx yang parser context for logging.
176 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
177 * when function returns.
178 * @param[in] arg Type of the input string to select method of checking character validity.
179 * @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 +0200180 * 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 +0200181 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
182 * @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 +0200183 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200184 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200185 *
186 * @return LY_ERR values.
187 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200188static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200189buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
190 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200191{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200192 int prefix;
193 unsigned int c;
194 size_t len;
195
196 /* get UTF8 code point (and number of bytes coding the character) */
197 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
198 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
199 (*input) -= len;
200 /* check character validity */
201 switch (arg) {
202 case Y_IDENTIF_ARG:
203 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
204 break;
205 case Y_PREF_IDENTIF_ARG:
206 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
207 break;
208 case Y_STR_ARG:
209 case Y_MAYBE_STR_ARG:
210 LY_CHECK_RET(check_stringchar(ctx, c));
211 break;
212 }
213
Michal Vasko7fbc8162018-09-17 10:35:16 +0200214 if (word_b && *word_b) {
215 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200216 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200217 return LY_EMEM;
218 }
219
220 /* in case of realloc */
221 *word_p = *word_b;
222 } else if (need_buf) {
223 /* first time we need a buffer, copy everything read up to now */
224 if (*word_len) {
225 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200226 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200227 *buf_len = *word_len;
228 memcpy(*word_b, *word_p, *word_len);
229 }
230
231 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200232 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200233 return LY_EMEM;
234 }
235
236 /* in case of realloc */
237 *word_p = *word_b;
238 } else {
239 /* just remember the first character pointer */
240 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200241 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200242 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200243 /* ... and update the word's length */
244 (*word_len) += len;
245 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200246 }
247
248 return LY_SUCCESS;
249}
250
Michal Vaskoea5abea2018-09-18 13:10:54 +0200251/**
252 * @brief Skip YANG comment in data.
253 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200254 * @param[in] ctx yang parser context for logging.
255 * @param[in,out] data Data to read from, automatically moved after the comment.
256 * @param[in] comment Type of the comment to process:
257 * 1 for a one-line comment,
258 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200259 *
260 * @return LY_ERR values.
261 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200262static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200263skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200264{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200265 /* internal statuses: 0 - comment ended,
266 * 1 - in line comment,
267 * 2 - in block comment,
268 * 3 - in block comment with last read character '*'
269 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200270 while (**data && comment) {
271 switch (comment) {
272 case 1:
273 if (**data == '\n') {
274 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200275 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200276 }
277 break;
278 case 2:
279 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200280 comment = 3;
281 } else if (**data == '\n') {
282 ++ctx->line;
283 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200284 break;
285 case 3:
286 if (**data == '/') {
287 comment = 0;
288 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200289 if (**data == '\n') {
290 ++ctx->line;
291 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200292 comment = 2;
293 }
294 break;
295 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200296 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200297 }
298
299 ++(*data);
300 }
301
302 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200303 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200304 return LY_EVALID;
305 }
306
307 return LY_SUCCESS;
308}
309
Michal Vaskoea5abea2018-09-18 13:10:54 +0200310/**
311 * @brief Read a quoted string from data.
312 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200313 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200314 * @param[in,out] data Data to read from, always moved to currently handled character.
315 * @param[in] arg Type of YANG keyword argument expected.
316 * @param[out] word_p Pointer to the read quoted string.
317 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
318 * set to NULL. Otherwise equal to \p word_p.
319 * @param[out] word_len Length of the read quoted string.
320 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
321 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
322 * indenation in the final quoted string.
323 *
324 * @return LY_ERR values.
325 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200326static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200327read_qstring(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len,
328 size_t *buf_len, int indent)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200329{
330 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
331 * 4 - string finished, now skipping whitespaces looking for +,
332 * 5 - string continues after +, skipping whitespaces */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200333 int string, str_nl_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200334 const char *c;
335
336 if (**data == '\"') {
337 /* indent of the " itself */
338 ++indent;
339 string = 2;
340 } else {
341 assert(**data == '\'');
342 string = 1;
343 }
344 ++(*data);
345
346 while (**data && string) {
347 switch (string) {
348 case 1:
349 switch (**data) {
350 case '\'':
351 /* string may be finished, but check for + */
352 string = 4;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200353 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200354 break;
355 default:
356 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200357 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 +0200358 break;
359 }
360 break;
361 case 2:
362 switch (**data) {
363 case '\"':
364 /* string may be finished, but check for + */
365 string = 4;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200366 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200367 break;
368 case '\\':
369 /* special character following */
370 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200371 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200372 break;
373 case ' ':
374 if (str_nl_indent) {
375 --str_nl_indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200376 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200377 } else {
378 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200379 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 +0200380 }
381 break;
382 case '\t':
383 if (str_nl_indent) {
384 if (str_nl_indent < 9) {
385 str_nl_indent = 0;
386 } else {
387 str_nl_indent -= 8;
388 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200389 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200390 } else {
391 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200392 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 +0200393 }
394 break;
395 case '\n':
396 str_nl_indent = indent;
397 if (indent) {
398 /* we will be removing the indents so we need our own buffer */
399 need_buf = 1;
400 }
401
402 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200403 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
404
405 /* maintain line number */
406 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200407 break;
408 default:
409 /* first non-whitespace character, clear current indent */
410 str_nl_indent = 0;
411
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));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200414 break;
415 }
416 break;
417 case 3:
418 /* string encoded characters */
419 switch (**data) {
420 case 'n':
421 c = "\n";
422 break;
423 case 't':
424 c = "\t";
425 break;
426 case '\"':
427 c = *data;
428 break;
429 case '\\':
430 c = *data;
431 break;
432 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200433 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.\n", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200434 return LY_EVALID;
435 }
436
437 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200438 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 +0200439
440 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200441 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200442 break;
443 case 4:
444 switch (**data) {
445 case '+':
446 /* string continues */
447 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200448 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200449 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200450 case '\n':
451 ++ctx->line;
452 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200453 case ' ':
454 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200455 /* just skip */
456 break;
457 default:
458 /* string is finished */
459 goto string_end;
460 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200461 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200462 break;
463 case 5:
464 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200465 case '\n':
466 ++ctx->line;
467 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200468 case ' ':
469 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200470 /* skip */
471 break;
472 case '\'':
473 string = 1;
474 break;
475 case '\"':
476 string = 2;
477 break;
478 default:
479 /* it must be quoted again */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200480 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.\n");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200481 return LY_EVALID;
482 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200483 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200484 break;
485 default:
486 return LY_EINT;
487 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200488 }
489
490string_end:
491 return LY_SUCCESS;
492}
493
Michal Vaskoea5abea2018-09-18 13:10:54 +0200494/**
495 * @brief Get another YANG string from the raw data.
496 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200497 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200498 * @param[in,out] data Data to read from, always moved to currently handled character.
499 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200500 * @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 +0200501 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
502 * set to NULL. Otherwise equal to \p word_p.
503 * @param[out] word_len Length of the read string.
504 *
505 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200506 */
507static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200508get_string(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 +0200509{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200510 size_t buf_len = 0;
511 int indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200512 LY_ERR ret;
513
514 /* word buffer - dynamically allocated */
515 *word_b = NULL;
516
517 /* word pointer - just a pointer to data */
518 *word_p = NULL;
519
520 *word_len = 0;
521 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200522 switch (**data) {
523 case '\'':
524 case '\"':
525 if (*word_len) {
526 /* we want strings always in a separate word, leave it */
527 goto str_end;
528 }
529 ret = read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len, indent);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200530 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200531 goto str_end;
532 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200533 if ((*data)[1] == '/') {
534 /* one-line comment */
535 (*data) += 2;
536 ret = skip_comment(ctx, data, 1);
537 } else if ((*data)[1] == '*') {
538 /* block comment */
539 (*data) += 2;
540 ret = skip_comment(ctx, data, 2);
541 } else {
542 /* not a comment after all */
543 --data;
544 ret = buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0);
545 }
546 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200547 break;
548 case ' ':
549 if (*word_len) {
550 /* word is finished */
551 goto str_end;
552 }
553 /* increase indent */
554 ++indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200555
556 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200557 break;
558 case '\t':
559 if (*word_len) {
560 /* word is finished */
561 goto str_end;
562 }
563 /* tabs count for 8 spaces */
564 indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200565
566 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200567 break;
568 case '\n':
569 if (*word_len) {
570 /* word is finished */
571 goto str_end;
572 }
573 /* reset indent */
574 indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200575
576 /* track line numbers */
577 ++ctx->line;
578
579 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200580 break;
581 case ';':
582 case '{':
583 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
584 /* word is finished */
585 goto str_end;
586 }
587
Radek Krejci44ceedc2018-10-02 15:54:31 +0200588 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200589 return LY_EVALID;
590 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200591 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 +0200592 break;
593 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200594 }
595
596str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200597 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200598 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200599 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
600 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
601 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200602 *word_p = *word_b;
603 }
604
605 return LY_SUCCESS;
606}
607
Michal Vaskoea5abea2018-09-18 13:10:54 +0200608/**
609 * @brief Get another YANG keyword from the raw data.
610 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200611 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200612 * @param[in,out] data Data to read from, always moved to currently handled character.
613 * @param[out] kw YANG keyword read.
614 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
615 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
616 *
617 * @return LY_ERR values.
618 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200619static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200620get_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 +0200621{
622 LY_ERR ret;
623 int prefix;
624 const char *word_start;
625 /* slash: 0 - nothing, 1 - last character was '/' */
626 int slash = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200627 unsigned int c;
628 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200629
630 if (word_p) {
631 *word_p = NULL;
632 *word_len = 0;
633 }
634
635 /* first skip "optsep", comments */
636 while (**data) {
637 if (slash) {
638 if (**data == '/') {
639 /* one-line comment */
640 ret = skip_comment(ctx, data, 1);
641 if (ret) {
642 return ret;
643 }
644 } else if (**data == '*') {
645 /* block comment */
646 ret = skip_comment(ctx, data, 2);
647 if (ret) {
648 return ret;
649 }
650 } else {
651 /* not a comment after all */
652 goto keyword_start;
653 }
654 slash = 0;
655 }
656
657 switch (**data) {
658 case '/':
659 slash = 1;
660 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200661 case '\n':
662 ++ctx->line;
663 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200664 case ' ':
665 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200666 /* skip whitespaces (optsep) */
667 break;
668 default:
669 /* either a keyword start or an invalid character */
670 goto keyword_start;
671 }
672
673 ++(*data);
674 }
675
676keyword_start:
677 word_start = *data;
678 *kw = YANG_NONE;
679
680 /* read the keyword itself */
681 switch (**data) {
682 case 'a':
683 ++(*data);
684 if (!strncmp(*data, "rgument", 7)) {
685 *data += 7;
686 *kw = YANG_ARGUMENT;
687 } else if (!strncmp(*data, "ugment", 6)) {
688 *data += 6;
689 *kw = YANG_AUGMENT;
690 } else if (!strncmp(*data, "ction", 5)) {
691 *data += 5;
692 *kw = YANG_ACTION;
693 } else if (!strncmp(*data, "ny", 2)) {
694 *data += 2;
695 if (!strncmp(*data, "data", 4)) {
696 *data += 4;
697 *kw = YANG_ANYDATA;
698 } else if (!strncmp(*data, "xml", 3)) {
699 *data += 3;
700 *kw = YANG_ANYXML;
701 }
702 }
703 break;
704 case 'b':
705 ++(*data);
706 if (!strncmp(*data, "ase", 3)) {
707 *data += 3;
708 *kw = YANG_BASE;
709 } else if (!strncmp(*data, "elongs-to", 9)) {
710 *data += 9;
711 *kw = YANG_BELONGS_TO;
712 } else if (!strncmp(*data, "it", 2)) {
713 *data += 2;
714 *kw = YANG_BIT;
715 }
716 break;
717 case 'c':
718 ++(*data);
719 if (!strncmp(*data, "ase", 3)) {
720 *data += 3;
721 *kw = YANG_CASE;
722 } else if (!strncmp(*data, "hoice", 5)) {
723 *data += 5;
724 *kw = YANG_CHOICE;
725 } else if (!strncmp(*data, "on", 2)) {
726 *data += 2;
727 if (!strncmp(*data, "fig", 3)) {
728 *data += 3;
729 *kw = YANG_CONFIG;
730 } else if (!strncmp(*data, "ta", 2)) {
731 *data += 2;
732 if (!strncmp(*data, "ct", 2)) {
733 *data += 2;
734 *kw = YANG_CONTACT;
735 } else if (!strncmp(*data, "iner", 4)) {
736 *data += 4;
737 *kw = YANG_CONTAINER;
738 }
739 }
740 }
741 break;
742 case 'd':
743 ++(*data);
744 if (**data == 'e') {
745 ++(*data);
746 if (!strncmp(*data, "fault", 5)) {
747 *data += 5;
748 *kw = YANG_DEFAULT;
749 } else if (!strncmp(*data, "scription", 9)) {
750 *data += 9;
751 *kw = YANG_DESCRIPTION;
752 } else if (!strncmp(*data, "viat", 4)) {
753 *data += 4;
754 if (**data == 'e') {
755 ++(*data);
756 *kw = YANG_DEVIATE;
757 } else if (!strncmp(*data, "ion", 3)) {
758 *data += 3;
759 *kw = YANG_DEVIATION;
760 }
761 }
762 }
763 break;
764 case 'e':
765 ++(*data);
766 if (!strncmp(*data, "num", 3)) {
767 *data += 3;
768 *kw = YANG_ENUM;
769 } else if (!strncmp(*data, "rror-", 5)) {
770 *data += 5;
771 if (!strncmp(*data, "app-tag", 7)) {
772 *data += 7;
773 *kw = YANG_ERROR_APP_TAG;
774 } else if (!strncmp(*data, "message", 7)) {
775 *data += 7;
776 *kw = YANG_ERROR_MESSAGE;
777 }
778 } else if (!strncmp(*data, "xtension", 8)) {
779 *data += 8;
780 *kw = YANG_EXTENSION;
781 }
782 break;
783 case 'f':
784 ++(*data);
785 if (!strncmp(*data, "eature", 6)) {
786 *data += 6;
787 *kw = YANG_FEATURE;
788 } else if (!strncmp(*data, "raction-digits", 14)) {
789 *data += 14;
790 *kw = YANG_FRACTION_DIGITS;
791 }
792 break;
793 case 'g':
794 ++(*data);
795 if (!strncmp(*data, "rouping", 7)) {
796 *data += 7;
797 *kw = YANG_GROUPING;
798 }
799 break;
800 case 'i':
801 ++(*data);
802 if (!strncmp(*data, "dentity", 7)) {
803 *data += 7;
804 *kw = YANG_IDENTITY;
805 } else if (!strncmp(*data, "f-feature", 9)) {
806 *data += 9;
807 *kw = YANG_IF_FEATURE;
808 } else if (!strncmp(*data, "mport", 5)) {
809 *data += 5;
810 *kw = YANG_IMPORT;
811 } else if (**data == 'n') {
812 ++(*data);
813 if (!strncmp(*data, "clude", 5)) {
814 *data += 5;
815 *kw = YANG_INCLUDE;
816 } else if (!strncmp(*data, "put", 3)) {
817 *data += 3;
818 *kw = YANG_INPUT;
819 }
820 }
821 break;
822 case 'k':
823 ++(*data);
824 if (!strncmp(*data, "ey", 2)) {
825 *data += 2;
826 *kw = YANG_KEY;
827 }
828 break;
829 case 'l':
830 ++(*data);
831 if (**data == 'e') {
832 ++(*data);
833 if (!strncmp(*data, "af", 2)) {
834 *data += 2;
835 if (**data != '-') {
836 *kw = YANG_LEAF;
837 } else if (!strncmp(*data, "-list", 5)) {
838 *data += 5;
839 *kw = YANG_LEAF_LIST;
840 }
841 } else if (!strncmp(*data, "ngth", 4)) {
842 *data += 4;
843 *kw = YANG_LENGTH;
844 }
845 } else if (!strncmp(*data, "ist", 3)) {
846 *data += 3;
847 *kw = YANG_LIST;
848 }
849 break;
850 case 'm':
851 ++(*data);
852 if (**data == 'a') {
853 ++(*data);
854 if (!strncmp(*data, "ndatory", 7)) {
855 *data += 7;
856 *kw = YANG_MANDATORY;
857 } else if (!strncmp(*data, "x-elements", 10)) {
858 *data += 10;
859 *kw = YANG_MAX_ELEMENTS;
860 }
861 } else if (!strncmp(*data, "in-elements", 11)) {
862 *data += 11;
863 *kw = YANG_MIN_ELEMENTS;
864 } else if (!strncmp(*data, "ust", 3)) {
865 *data += 3;
866 *kw = YANG_MUST;
867 } else if (!strncmp(*data, "od", 2)) {
868 *data += 2;
869 if (!strncmp(*data, "ule", 3)) {
870 *data += 3;
871 *kw = YANG_MODULE;
872 } else if (!strncmp(*data, "ifier", 5)) {
873 *data += 3;
874 *kw = YANG_MODIFIER;
875 }
876 }
877 break;
878 case 'n':
879 ++(*data);
880 if (!strncmp(*data, "amespace", 8)) {
881 *data += 8;
882 *kw = YANG_NAMESPACE;
883 } else if (!strncmp(*data, "otification", 11)) {
884 *data += 11;
885 *kw = YANG_NOTIFICATION;
886 }
887 break;
888 case 'o':
889 ++(*data);
890 if (**data == 'r') {
891 ++(*data);
892 if (!strncmp(*data, "dered-by", 8)) {
893 *data += 8;
894 *kw = YANG_ORDERED_BY;
895 } else if (!strncmp(*data, "ganization", 10)) {
896 *data += 10;
897 *kw = YANG_ORGANIZATION;
898 }
899 } else if (!strncmp(*data, "utput", 5)) {
900 *data += 5;
901 *kw = YANG_OUTPUT;
902 }
903 break;
904 case 'p':
905 ++(*data);
906 if (!strncmp(*data, "at", 2)) {
907 *data += 2;
908 if (**data == 'h') {
909 ++(*data);
910 *kw = YANG_PATH;
911 } else if (!strncmp(*data, "tern", 4)) {
912 *data += 4;
913 *kw = YANG_PATTERN;
914 }
915 } else if (!strncmp(*data, "osition", 7)) {
916 *data += 7;
917 *kw = YANG_POSITION;
918 } else if (!strncmp(*data, "re", 2)) {
919 *data += 2;
920 if (!strncmp(*data, "fix", 3)) {
921 *data += 3;
922 *kw = YANG_PREFIX;
923 } else if (!strncmp(*data, "sence", 5)) {
924 *data += 5;
925 *kw = YANG_PRESENCE;
926 }
927 }
928 break;
929 case 'r':
930 ++(*data);
931 if (!strncmp(*data, "ange", 4)) {
932 *data += 4;
933 *kw = YANG_RANGE;
934 } else if (**data == 'e') {
935 ++(*data);
936 if (**data == 'f') {
937 ++(*data);
938 if (!strncmp(*data, "erence", 6)) {
939 *data += 6;
940 *kw = YANG_REFERENCE;
941 } else if (!strncmp(*data, "ine", 3)) {
942 *data += 3;
943 *kw = YANG_REFINE;
944 }
945 } else if (!strncmp(*data, "quire-instance", 14)) {
946 *data += 14;
947 *kw = YANG_REQUIRE_INSTANCE;
948 } else if (!strncmp(*data, "vision", 6)) {
949 *data += 6;
950 if (**data != '-') {
951 *kw = YANG_REVISION;
952 } else if (!strncmp(*data, "-date", 5)) {
953 *data += 5;
954 *kw = YANG_REVISION_DATE;
955 }
956 }
957 } else if (!strncmp(*data, "pc", 2)) {
958 *data += 2;
959 *kw = YANG_RPC;
960 }
961 break;
962 case 's':
963 ++(*data);
964 if (!strncmp(*data, "tatus", 5)) {
965 *data += 5;
966 *kw = YANG_STATUS;
967 } else if (!strncmp(*data, "ubmodule", 8)) {
968 *data += 8;
969 *kw = YANG_SUBMODULE;
970 }
971 break;
972 case 't':
973 ++(*data);
974 if (!strncmp(*data, "ype", 3)) {
975 *data += 3;
976 if (**data != 'd') {
977 *kw = YANG_TYPE;
978 } else if (!strncmp(*data, "def", 3)) {
979 *data += 3;
980 *kw = YANG_TYPEDEF;
981 }
982 }
983 break;
984 case 'u':
985 ++(*data);
986 if (!strncmp(*data, "ni", 2)) {
987 *data += 2;
988 if (!strncmp(*data, "que", 3)) {
989 *data += 3;
990 *kw = YANG_UNIQUE;
991 } else if (!strncmp(*data, "ts", 2)) {
992 *data += 2;
993 *kw = YANG_UNITS;
994 }
995 } else if (!strncmp(*data, "ses", 3)) {
996 *data += 3;
997 *kw = YANG_USES;
998 }
999 break;
1000 case 'v':
1001 ++(*data);
1002 if (!strncmp(*data, "alue", 4)) {
1003 *data += 4;
1004 *kw = YANG_VALUE;
1005 }
1006 break;
1007 case 'w':
1008 ++(*data);
1009 if (!strncmp(*data, "hen", 3)) {
1010 *data += 3;
1011 *kw = YANG_WHEN;
1012 }
1013 break;
1014 case 'y':
1015 ++(*data);
1016 if (!strncmp(*data, "ang-version", 11)) {
1017 *data += 11;
1018 *kw = YANG_YANG_VERSION;
1019 } else if (!strncmp(*data, "in-element", 10)) {
1020 *data += 10;
1021 *kw = YANG_YIN_ELEMENT;
1022 }
1023 break;
1024 case ';':
1025 ++(*data);
1026 *kw = YANG_SEMICOLON;
1027 break;
1028 case '{':
1029 ++(*data);
1030 *kw = YANG_LEFT_BRACE;
1031 break;
1032 case '}':
1033 ++(*data);
1034 *kw = YANG_RIGHT_BRACE;
1035 break;
1036 default:
1037 break;
1038 }
1039
1040 if (*kw != YANG_NONE) {
1041 /* make sure we have the whole keyword */
1042 switch (**data) {
1043 case ' ':
1044 case '\t':
1045 case '\n':
1046 /* mandatory "sep" */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001047 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001048 break;
1049 default:
1050 ++(*data);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001051 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
1052 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001053 return LY_EVALID;
1054 }
1055 } else {
1056 /* still can be an extension */
1057 prefix = 0;
1058 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001059 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
1060 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
1061 /* check character validity */
1062 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001063 }
1064 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001065 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001066 return LY_EVALID;
1067 }
1068
1069 /* prefix is mandatory for extension instances */
1070 if (prefix != 1) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001071 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001072 return LY_EVALID;
1073 }
1074
1075 *kw = YANG_CUSTOM;
1076 }
1077
1078 if (word_p) {
1079 *word_p = (char *)word_start;
1080 *word_len = *data - word_start;
1081 }
1082
1083 return LY_SUCCESS;
1084}
1085
Michal Vaskoea5abea2018-09-18 13:10:54 +02001086/**
1087 * @brief Parse extension instance substatements.
1088 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001089 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001090 * @param[in,out] data Data to read from, always moved to currently handled character.
1091 * @param[in] word Extension instance substatement name (keyword).
1092 * @param[in] word_len Extension instance substatement name length.
1093 * @param[in,out] child Children of this extension instance to add to.
1094 *
1095 * @return LY_ERR values.
1096 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001097static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001098parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001099 struct lysp_stmt **child)
1100{
1101 char *buf;
1102 LY_ERR ret = 0;
1103 enum yang_keyword kw;
1104 struct lysp_stmt *stmt, *par_child;
1105
1106 stmt = calloc(1, sizeof *stmt);
1107 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
1108
Radek Krejci44ceedc2018-10-02 15:54:31 +02001109 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001110
1111 /* get optional argument */
1112 ret = get_string(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001113 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001114
Radek Krejci0ae092d2018-09-20 16:43:19 +02001115 if (word) {
1116 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001117 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001118 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001119 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +02001120 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001121 }
1122
1123 /* insert into parent statements */
1124 if (!*child) {
1125 *child = stmt;
1126 } else {
1127 for (par_child = *child; par_child->next; par_child = par_child->next);
1128 par_child->next = stmt;
1129 }
1130
1131 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001132 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001133
1134 ret = parse_ext_substmt(ctx, data, word, word_len, &stmt->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001135 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001136 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001137 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001138
1139 return ret;
1140}
1141
Michal Vaskoea5abea2018-09-18 13:10:54 +02001142/**
1143 * @brief Parse extension instance.
1144 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001145 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001146 * @param[in,out] data Data to read from, always moved to currently handled character.
1147 * @param[in] ext_name Extension instance substatement name (keyword).
1148 * @param[in] ext_name_len Extension instance substatement name length.
1149 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1150 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1151 * @param[in,out] exts Extension instances to add to.
1152 *
1153 * @return LY_ERR values.
1154 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001155static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001156parse_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 +02001157 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1158{
1159 LY_ERR ret = 0;
1160 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001161 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001162 struct lysp_ext_instance *e;
1163 enum yang_keyword kw;
1164
1165 LYSP_ARRAY_NEW_RET(ctx, exts, e, LY_EMEM);
1166
1167 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001168 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001169 e->insubstmt = insubstmt;
1170 e->insubstmt_index = insubstmt_index;
1171
1172 /* get optional argument */
1173 ret = get_string(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001174 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001175
Radek Krejci0ae092d2018-09-20 16:43:19 +02001176 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001177 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001178 }
1179
1180 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001181 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001182
1183 ret = parse_ext_substmt(ctx, data, word, word_len, &e->child);
Radek Krejcic59bc972018-09-17 16:13:06 +02001184 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001185 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001186 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001187
1188 return ret;
1189}
1190
Michal Vaskoea5abea2018-09-18 13:10:54 +02001191/**
1192 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1193 * description, etc...
1194 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001195 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001196 * @param[in,out] data Data to read from, always moved to currently handled character.
1197 * @param[in] substmt Type of this substatement.
1198 * @param[in] substmt_index Index of this substatement.
1199 * @param[in,out] value Place to store the parsed value.
1200 * @param[in] arg Type of the YANG keyword argument (of the value).
1201 * @param[in,out] exts Extension instances to add to.
1202 *
1203 * @return LY_ERR values.
1204 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001205static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001206parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001207 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1208{
1209 LY_ERR ret = 0;
1210 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001211 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001212 enum yang_keyword kw;
1213
1214 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001215 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001216 return LY_EVALID;
1217 }
1218
1219 /* get value */
1220 ret = get_string(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001221 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001222
1223 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001224 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001225
1226 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001227 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001228
1229 switch (kw) {
1230 case YANG_CUSTOM:
1231 ret = parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001232 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001233 break;
1234 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001235 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001236 return LY_EVALID;
1237 }
1238 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001239 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001240
1241 return ret;
1242}
1243
Michal Vaskoea5abea2018-09-18 13:10:54 +02001244/**
1245 * @brief Parse the yang-version statement.
1246 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001247 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001248 * @param[in,out] data Data to read from, always moved to currently handled character.
1249 * @param[in] mod Module to store the parsed information in.
1250 *
1251 * @return LY_ERR values.
1252 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001253static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001254parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001255{
1256 LY_ERR ret = 0;
1257 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001258 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001259 enum yang_keyword kw;
1260
1261 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001262 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001263 return LY_EVALID;
1264 }
1265
1266 /* get value */
1267 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001268 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001269
1270 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1271 mod->version = LYS_VERSION_1_0;
1272 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1273 mod->version = LYS_VERSION_1_1;
1274 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001275 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001276 free(buf);
1277 return LY_EVALID;
1278 }
1279 free(buf);
1280
1281 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001282 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001283
1284 switch (kw) {
1285 case YANG_CUSTOM:
1286 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001287 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001288 break;
1289 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001290 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001291 return LY_EVALID;
1292 }
1293 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001294 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001295
1296 return ret;
1297}
1298
Michal Vaskoea5abea2018-09-18 13:10:54 +02001299/**
1300 * @brief Parse the belongs-to statement.
1301 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001302 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001303 * @param[in,out] data Data to read from, always moved to currently handled character.
1304 * @param[in,out] belongsto Place to store the parsed value.
1305 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1306 * @param[in,out] exts Extension instances to add to.
1307 *
1308 * @return LY_ERR values.
1309 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001310static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001311parse_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 +02001312{
1313 LY_ERR ret = 0;
1314 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001315 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001316 enum yang_keyword kw;
1317
1318 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001319 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001320 return LY_EVALID;
1321 }
1322
1323 /* get value */
1324 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001325 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001326
Radek Krejci44ceedc2018-10-02 15:54:31 +02001327 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001328 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001329 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001330
1331 switch (kw) {
1332 case YANG_PREFIX:
1333 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts);
1334 break;
1335 case YANG_CUSTOM:
1336 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts);
1337 break;
1338 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001339 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001340 return LY_EVALID;
1341 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001342 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001343 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001344 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001345
1346 /* mandatory substatements */
1347 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001348 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001349 return LY_EVALID;
1350 }
1351
1352 return ret;
1353}
1354
Michal Vaskoea5abea2018-09-18 13:10:54 +02001355/**
1356 * @brief Parse the revision-date statement.
1357 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001358 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001359 * @param[in,out] data Data to read from, always moved to currently handled character.
1360 * @param[in,out] rev Array to store the parsed value in.
1361 * @param[in,out] exts Extension instances to add to.
1362 *
1363 * @return LY_ERR values.
1364 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001365static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001366parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001367{
1368 LY_ERR ret = 0;
1369 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001370 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001371 enum yang_keyword kw;
1372
1373 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001374 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001375 return LY_EVALID;
1376 }
1377
1378 /* get value */
1379 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001380 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001381
1382 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001383 if (lysp_check_date(ctx->ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001384 free(buf);
1385 return LY_EVALID;
1386 }
1387
1388 /* store value and spend buf if allocated */
1389 strncpy(rev, word, word_len);
1390 free(buf);
1391
1392 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001393 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001394
1395 switch (kw) {
1396 case YANG_CUSTOM:
1397 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001398 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001399 break;
1400 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001401 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001402 return LY_EVALID;
1403 }
1404 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001405 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001406
1407 return ret;
1408}
1409
Michal Vaskoea5abea2018-09-18 13:10:54 +02001410/**
1411 * @brief Parse the include statement.
1412 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001413 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001414 * @param[in,out] data Data to read from, always moved to currently handled character.
1415 * @param[in,out] includes Parsed includes to add to.
1416 *
1417 * @return LY_ERR values.
1418 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001419static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001420parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_include **includes)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001421{
1422 LY_ERR ret = 0;
1423 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001424 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001425 enum yang_keyword kw;
1426 struct lysp_include *inc;
1427
1428 LYSP_ARRAY_NEW_RET(ctx, includes, inc, LY_EMEM);
1429
1430 /* get value */
1431 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001432 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001433
Radek Krejci44ceedc2018-10-02 15:54:31 +02001434 INSERT_WORD(ctx, buf, inc->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001435 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001436 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001437
1438 switch (kw) {
1439 case YANG_DESCRIPTION:
1440 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts);
1441 break;
1442 case YANG_REFERENCE:
1443 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts);
1444 break;
1445 case YANG_REVISION_DATE:
1446 ret = parse_revisiondate(ctx, data, inc->rev, &inc->exts);
1447 break;
1448 case YANG_CUSTOM:
1449 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts);
1450 break;
1451 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001452 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001453 return LY_EVALID;
1454 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001455 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001456 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001457 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001458
1459 return ret;
1460}
1461
Michal Vaskoea5abea2018-09-18 13:10:54 +02001462/**
1463 * @brief Parse the import statement.
1464 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001465 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001466 * @param[in,out] data Data to read from, always moved to currently handled character.
1467 * @param[in,out] imports Parsed imports to add to.
1468 *
1469 * @return LY_ERR values.
1470 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001471static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001472parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_import **imports)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001473{
1474 LY_ERR ret = 0;
1475 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001476 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001477 enum yang_keyword kw;
1478 struct lysp_import *imp;
1479
1480 LYSP_ARRAY_NEW_RET(ctx, imports, imp, LY_EVALID);
1481
1482 /* get value */
1483 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001484 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001485
Radek Krejci44ceedc2018-10-02 15:54:31 +02001486 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001487 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001488 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001489
1490 switch (kw) {
1491 case YANG_PREFIX:
1492 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts);
1493 break;
1494 case YANG_DESCRIPTION:
1495 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts);
1496 break;
1497 case YANG_REFERENCE:
1498 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts);
1499 break;
1500 case YANG_REVISION_DATE:
1501 ret = parse_revisiondate(ctx, data, imp->rev, &imp->exts);
1502 break;
1503 case YANG_CUSTOM:
1504 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts);
1505 break;
1506 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001507 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001508 return LY_EVALID;
1509 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001510 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001511 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001512 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001513
1514 /* mandatory substatements */
1515 if (!imp->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001516 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001517 return LY_EVALID;
1518 }
1519
1520 return ret;
1521}
1522
Michal Vaskoea5abea2018-09-18 13:10:54 +02001523/**
1524 * @brief Parse the revision statement.
1525 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001526 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001527 * @param[in,out] data Data to read from, always moved to currently handled character.
1528 * @param[in,out] revs Parsed revisions to add to.
1529 *
1530 * @return LY_ERR values.
1531 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001532static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001533parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001534{
1535 LY_ERR ret = 0;
1536 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001537 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001538 enum yang_keyword kw;
1539 struct lysp_revision *rev;
1540
1541 LYSP_ARRAY_NEW_RET(ctx, revs, rev, LY_EMEM);
1542
1543 /* get value */
1544 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001545 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001546
1547 /* check value */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001548 if (lysp_check_date(ctx->ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001549 return LY_EVALID;
1550 }
1551
1552 strncpy(rev->rev, word, word_len);
1553 free(buf);
1554
1555 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001556 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001557
1558 switch (kw) {
1559 case YANG_DESCRIPTION:
1560 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts);
1561 break;
1562 case YANG_REFERENCE:
1563 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts);
1564 break;
1565 case YANG_CUSTOM:
1566 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts);
1567 break;
1568 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001569 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001570 return LY_EVALID;
1571 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001572 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001573 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001574 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001575
1576 return ret;
1577}
1578
Michal Vaskoea5abea2018-09-18 13:10:54 +02001579/**
1580 * @brief Parse a generic text field that can have more instances such as base.
1581 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001582 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001583 * @param[in,out] data Data to read from, always moved to currently handled character.
1584 * @param[in] substmt Type of this substatement.
1585 * @param[in,out] texts Parsed values to add to.
1586 * @param[in] arg Type of the expected argument.
1587 * @param[in,out] exts Extension instances to add to.
1588 *
1589 * @return LY_ERR values.
1590 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001591static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001592parse_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 +02001593 struct lysp_ext_instance **exts)
1594{
1595 LY_ERR ret = 0;
1596 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001597 size_t count, word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001598 enum yang_keyword kw;
1599
1600 /* allocate new pointer */
1601 for (count = 1; (*texts) && (*texts)[count - 1]; ++count);
1602 *texts = realloc(*texts, count * sizeof **texts);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001603 LY_CHECK_ERR_RET(!*texts, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001604
1605 /* get value */
1606 ret = get_string(ctx, data, arg, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001607 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001608
Radek Krejci44ceedc2018-10-02 15:54:31 +02001609 INSERT_WORD(ctx, buf, (*texts)[count - 1], word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001610 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001611 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001612
1613 switch (kw) {
1614 case YANG_CUSTOM:
1615 ret = parse_ext(ctx, data, word, word_len, substmt, count - 1, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001616 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001617 break;
1618 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001619 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001620 return LY_EVALID;
1621 }
1622 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001623 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001624
1625 return ret;
1626}
1627
Michal Vaskoea5abea2018-09-18 13:10:54 +02001628/**
1629 * @brief Parse the config statement.
1630 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001631 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001632 * @param[in,out] data Data to read from, always moved to currently handled character.
1633 * @param[in,out] flags Flags to add to.
1634 * @param[in,out] exts Extension instances to add to.
1635 *
1636 * @return LY_ERR values.
1637 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001638static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001639parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001640{
1641 LY_ERR ret = 0;
1642 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001643 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001644 enum yang_keyword kw;
1645
1646 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001647 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001648 return LY_EVALID;
1649 }
1650
1651 /* get value */
1652 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001653 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001654
1655 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1656 *flags |= LYS_CONFIG_W;
1657 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1658 *flags |= LYS_CONFIG_R;
1659 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001660 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001661 free(buf);
1662 return LY_EVALID;
1663 }
1664 free(buf);
1665
1666 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001667 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001668
1669 switch (kw) {
1670 case YANG_CUSTOM:
1671 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001672 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001673 break;
1674 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001675 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001676 return LY_EVALID;
1677 }
1678 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001679 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001680
1681 return ret;
1682}
1683
Michal Vaskoea5abea2018-09-18 13:10:54 +02001684/**
1685 * @brief Parse the mandatory statement.
1686 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001687 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001688 * @param[in,out] data Data to read from, always moved to currently handled character.
1689 * @param[in,out] flags Flags to add to.
1690 * @param[in,out] exts Extension instances to add to.
1691 *
1692 * @return LY_ERR values.
1693 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001694static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001695parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001696{
1697 LY_ERR ret = 0;
1698 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001699 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001700 enum yang_keyword kw;
1701
1702 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001703 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001704 return LY_EVALID;
1705 }
1706
1707 /* get value */
1708 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001709 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001710
1711 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1712 *flags |= LYS_MAND_TRUE;
1713 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1714 *flags |= LYS_MAND_FALSE;
1715 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001716 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001717 free(buf);
1718 return LY_EVALID;
1719 }
1720 free(buf);
1721
1722 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001723 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001724
1725 switch (kw) {
1726 case YANG_CUSTOM:
1727 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001728 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001729 break;
1730 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001731 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001732 return LY_EVALID;
1733 }
1734 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001735 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001736
1737 return ret;
1738}
1739
Michal Vaskoea5abea2018-09-18 13:10:54 +02001740/**
1741 * @brief Parse a restriction such as range or length.
1742 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001743 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001744 * @param[in,out] data Data to read from, always moved to currently handled character.
1745 * @param[in] restr_kw Type of this particular restriction.
1746 * @param[in,out] exts Extension instances to add to.
1747 *
1748 * @return LY_ERR values.
1749 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001750static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001751parse_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 +02001752{
1753 LY_ERR ret = 0;
1754 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001755 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001756 enum yang_keyword kw;
1757
1758 /* get value */
1759 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001760 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001761
Radek Krejci44ceedc2018-10-02 15:54:31 +02001762 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001763 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001764 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001765
1766 switch (kw) {
1767 case YANG_DESCRIPTION:
1768 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
1769 break;
1770 case YANG_REFERENCE:
1771 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
1772 break;
1773 case YANG_ERROR_APP_TAG:
1774 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
1775 break;
1776 case YANG_ERROR_MESSAGE:
1777 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
1778 break;
1779 case YANG_CUSTOM:
1780 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
1781 break;
1782 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001783 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001784 return LY_EVALID;
1785 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001786 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001787 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001788 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001789
1790 return ret;
1791}
1792
Michal Vaskoea5abea2018-09-18 13:10:54 +02001793/**
1794 * @brief Parse a restriction that can have more instances such as must.
1795 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001796 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001797 * @param[in,out] data Data to read from, always moved to currently handled character.
1798 * @param[in] restr_kw Type of this particular restriction.
1799 * @param[in,out] restrs Restrictions to add to.
1800 *
1801 * @return LY_ERR values.
1802 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001803static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001804parse_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 +02001805{
1806 struct lysp_restr *restr;
1807
1808 LYSP_ARRAY_NEW_RET(ctx, restrs, restr, LY_EMEM);
1809
1810 return parse_restr(ctx, data, restr_kw, restr);
1811}
1812
Michal Vaskoea5abea2018-09-18 13:10:54 +02001813/**
1814 * @brief Parse the status statement.
1815 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001816 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001817 * @param[in,out] data Data to read from, always moved to currently handled character.
1818 * @param[in,out] flags Flags to add to.
1819 * @param[in,out] exts Extension instances to add to.
1820 *
1821 * @return LY_ERR values.
1822 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001823static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001824parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001825{
1826 LY_ERR ret = 0;
1827 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001828 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001829 enum yang_keyword kw;
1830
1831 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001832 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001833 return LY_EVALID;
1834 }
1835
1836 /* get value */
1837 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001838 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001839
1840 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1841 *flags |= LYS_STATUS_CURR;
1842 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1843 *flags |= LYS_STATUS_DEPRC;
1844 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1845 *flags |= LYS_STATUS_OBSLT;
1846 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001847 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001848 free(buf);
1849 return LY_EVALID;
1850 }
1851 free(buf);
1852
1853 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001854 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001855
1856 switch (kw) {
1857 case YANG_CUSTOM:
1858 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02001859 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001860 break;
1861 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001862 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001863 return LY_EVALID;
1864 }
1865 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001866 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001867
1868 return ret;
1869}
1870
Michal Vaskoea5abea2018-09-18 13:10:54 +02001871/**
1872 * @brief Parse the when statement.
1873 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001874 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001875 * @param[in,out] data Data to read from, always moved to currently handled character.
1876 * @param[in,out] when_p When pointer to parse to.
1877 *
1878 * @return LY_ERR values.
1879 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001880static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001881parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001882{
1883 LY_ERR ret = 0;
1884 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001885 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001886 enum yang_keyword kw;
1887 struct lysp_when *when;
1888
1889 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001890 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001891 return LY_EVALID;
1892 }
1893
1894 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001895 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001896 *when_p = when;
1897
1898 /* get value */
1899 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001900 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001901
Radek Krejci44ceedc2018-10-02 15:54:31 +02001902 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001903 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001904 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001905
1906 switch (kw) {
1907 case YANG_DESCRIPTION:
1908 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts);
1909 break;
1910 case YANG_REFERENCE:
1911 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts);
1912 break;
1913 case YANG_CUSTOM:
1914 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts);
1915 break;
1916 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001917 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001918 return LY_EVALID;
1919 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001920 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001921 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001922 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001923
1924 return ret;
1925}
1926
Michal Vaskoea5abea2018-09-18 13:10:54 +02001927/**
1928 * @brief Parse the anydata or anyxml statement.
1929 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001930 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001931 * @param[in,out] data Data to read from, always moved to currently handled character.
1932 * @param[in] kw Type of this particular keyword.
1933 * @param[in,out] siblings Siblings to add to.
1934 *
1935 * @return LY_ERR values.
1936 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001937static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001938parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001939{
1940 LY_ERR ret = 0;
1941 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001942 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001943 struct lysp_node *iter;
1944 struct lysp_node_anydata *any;
1945
1946 /* create structure */
1947 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001948 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001949 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
1950
1951 /* insert into siblings */
1952 if (!*siblings) {
1953 *siblings = (struct lysp_node *)any;
1954 } else {
1955 for (iter = *siblings; iter->next; iter = iter->next);
1956 iter->next = (struct lysp_node *)any;
1957 }
1958
1959 /* get name */
1960 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02001961 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001962
Radek Krejci44ceedc2018-10-02 15:54:31 +02001963 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001964
1965 /* parse substatements */
1966 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02001967 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001968
1969 switch (kw) {
1970 case YANG_CONFIG:
1971 ret = parse_config(ctx, data, &any->flags, &any->exts);
1972 break;
1973 case YANG_DESCRIPTION:
1974 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts);
1975 break;
1976 case YANG_IF_FEATURE:
1977 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts);
1978 break;
1979 case YANG_MANDATORY:
1980 ret = parse_mandatory(ctx, data, &any->flags, &any->exts);
1981 break;
1982 case YANG_MUST:
1983 ret = parse_restrs(ctx, data, kw, &any->musts);
1984 break;
1985 case YANG_REFERENCE:
1986 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts);
1987 break;
1988 case YANG_STATUS:
1989 ret = parse_status(ctx, data, &any->flags, &any->exts);
1990 break;
1991 case YANG_WHEN:
1992 ret = parse_when(ctx, data, &any->when);
1993 break;
1994 case YANG_CUSTOM:
1995 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts);
1996 break;
1997 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001998 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001999 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002000 return LY_EVALID;
2001 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002002 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002003 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002004 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002005
2006 return ret;
2007}
2008
Michal Vaskoea5abea2018-09-18 13:10:54 +02002009/**
2010 * @brief Parse the value or position statement. Substatement of type enum statement.
2011 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002012 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002013 * @param[in,out] data Data to read from, always moved to currently handled character.
2014 * @param[in] val_kw Type of this particular keyword.
2015 * @param[in,out] value Value to write to.
2016 * @param[in,out] flags Flags to write to.
2017 * @param[in,out] exts Extension instances to add to.
2018 *
2019 * @return LY_ERR values.
2020 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002021static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002022parse_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 +02002023 struct lysp_ext_instance **exts)
2024{
2025 LY_ERR ret = 0;
2026 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002027 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002028 long int num;
2029 unsigned long int unum;
2030 enum yang_keyword kw;
2031
2032 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002033 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002034 return LY_EVALID;
2035 }
2036 *flags |= LYS_SET_VALUE;
2037
2038 /* get value */
2039 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002040 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002041
2042 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 +02002043 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002044 free(buf);
2045 return LY_EVALID;
2046 }
2047
2048 errno = 0;
2049 if (val_kw == YANG_VALUE) {
2050 num = strtol(word, &ptr, 10);
2051 } else {
2052 unum = strtoul(word, &ptr, 10);
2053 }
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, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002057 free(buf);
2058 return LY_EVALID;
2059 }
2060 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002061 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002062 free(buf);
2063 return LY_EVALID;
2064 }
2065 if (val_kw == YANG_VALUE) {
2066 *value = num;
2067 } else {
2068 *value = unum;
2069 }
2070 free(buf);
2071
2072 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002073 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002074
2075 switch (kw) {
2076 case YANG_CUSTOM:
2077 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 +02002078 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002079 break;
2080 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002081 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002082 return LY_EVALID;
2083 }
2084 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002085 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002086
2087 return ret;
2088}
2089
Michal Vaskoea5abea2018-09-18 13:10:54 +02002090/**
2091 * @brief Parse the enum or bit statement. Substatement of type statement.
2092 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002093 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002094 * @param[in,out] data Data to read from, always moved to currently handled character.
2095 * @param[in] enum_kw Type of this particular keyword.
2096 * @param[in,out] enums Enums or bits to add to.
2097 *
2098 * @return LY_ERR values.
2099 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002100static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002101parse_type_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 +02002102{
2103 LY_ERR ret = 0;
2104 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002105 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002106 enum yang_keyword kw;
2107 struct lysp_type_enum *enm;
2108
2109 LYSP_ARRAY_NEW_RET(ctx, enums, enm, LY_EMEM);
2110
2111 /* get value */
2112 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002113 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002114
Radek Krejci44ceedc2018-10-02 15:54:31 +02002115 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002116 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002117 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002118
2119 switch (kw) {
2120 case YANG_DESCRIPTION:
2121 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts);
2122 break;
2123 case YANG_IF_FEATURE:
2124 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts);
2125 break;
2126 case YANG_REFERENCE:
2127 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts);
2128 break;
2129 case YANG_STATUS:
2130 ret = parse_status(ctx, data, &enm->flags, &enm->exts);
2131 break;
2132 case YANG_VALUE:
2133 case YANG_POSITION:
2134 ret = parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts);
2135 break;
2136 case YANG_CUSTOM:
2137 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts);
2138 break;
2139 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002140 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002141 return LY_EVALID;
2142 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002143 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002144 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002145 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002146
2147 return ret;
2148}
2149
Michal Vaskoea5abea2018-09-18 13:10:54 +02002150/**
2151 * @brief Parse the fraction-digits statement. Substatement of type statement.
2152 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002153 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002154 * @param[in,out] data Data to read from, always moved to currently handled character.
2155 * @param[in,out] fracdig Value to write to.
2156 * @param[in,out] exts Extension instances to add to.
2157 *
2158 * @return LY_ERR values.
2159 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002160static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002161parse_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 +02002162{
2163 LY_ERR ret = 0;
2164 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002165 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002166 unsigned long int num;
2167 enum yang_keyword kw;
2168
2169 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002170 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002171 return LY_EVALID;
2172 }
2173
2174 /* get value */
2175 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002176 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002177
2178 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002179 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002180 free(buf);
2181 return LY_EVALID;
2182 }
2183
2184 errno = 0;
2185 num = strtoul(word, &ptr, 10);
2186 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002187 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002188 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189 free(buf);
2190 return LY_EVALID;
2191 }
2192 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002193 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002194 free(buf);
2195 return LY_EVALID;
2196 }
2197 *fracdig = num;
2198 free(buf);
2199
2200 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002201 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002202
2203 switch (kw) {
2204 case YANG_CUSTOM:
2205 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002206 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002207 break;
2208 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002209 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002210 return LY_EVALID;
2211 }
2212 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002213 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002214
2215 return ret;
2216}
2217
Michal Vaskoea5abea2018-09-18 13:10:54 +02002218/**
2219 * @brief Parse the require-instance statement. Substatement of type statement.
2220 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002221 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002222 * @param[in,out] data Data to read from, always moved to currently handled character.
2223 * @param[in,out] reqinst Value to write to.
2224 * @param[in,out] flags Flags to write to.
2225 * @param[in,out] exts Extension instances to add to.
2226 *
2227 * @return LY_ERR values.
2228 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002229static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002230parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002231 struct lysp_ext_instance **exts)
2232{
2233 LY_ERR ret = 0;
2234 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002235 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002236 enum yang_keyword kw;
2237
2238 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002239 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002240 return LY_EVALID;
2241 }
2242 *flags |= LYS_SET_REQINST;
2243
2244 /* get value */
2245 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002246 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002247
2248 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2249 *reqinst = 1;
2250 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002251 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002252 free(buf);
2253 return LY_EVALID;
2254 }
2255 free(buf);
2256
2257 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002258 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002259
2260 switch (kw) {
2261 case YANG_CUSTOM:
2262 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002263 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002264 break;
2265 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002266 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002267 return LY_EVALID;
2268 }
2269 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002270 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002271
2272 return ret;
2273}
2274
Michal Vaskoea5abea2018-09-18 13:10:54 +02002275/**
2276 * @brief Parse the modifier statement. Substatement of type pattern statement.
2277 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002278 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002279 * @param[in,out] data Data to read from, always moved to currently handled character.
2280 * @param[in,out] pat Value to write to.
2281 * @param[in,out] exts Extension instances to add to.
2282 *
2283 * @return LY_ERR values.
2284 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002285static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002286parse_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 +02002287{
2288 LY_ERR ret = 0;
2289 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002290 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002291 enum yang_keyword kw;
2292
2293 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002294 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002295 return LY_EVALID;
2296 }
2297
2298 /* get value */
2299 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002300 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002301
2302 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002303 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002304 free(buf);
2305 return LY_EVALID;
2306 }
2307 free(buf);
2308
2309 /* replace the value in the dictionary */
2310 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002311 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002312 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002313 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002314
2315 assert(buf[0] == 0x06);
2316 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002317 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002318
2319 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002320 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002321
2322 switch (kw) {
2323 case YANG_CUSTOM:
2324 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002325 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002326 break;
2327 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002328 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002329 return LY_EVALID;
2330 }
2331 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002332 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002333
2334 return ret;
2335}
2336
Michal Vaskoea5abea2018-09-18 13:10:54 +02002337/**
2338 * @brief Parse the pattern statement. Substatement of type statement.
2339 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002340 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002341 * @param[in,out] data Data to read from, always moved to currently handled character.
2342 * @param[in,out] patterns Restrictions to add to.
2343 *
2344 * @return LY_ERR values.
2345 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002346static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002347parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002348{
2349 LY_ERR ret = 0;
2350 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002351 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002352 enum yang_keyword kw;
2353 struct lysp_restr *restr;
2354
2355 LYSP_ARRAY_NEW_RET(ctx, patterns, restr, LY_EMEM);
2356
2357 /* get value */
2358 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002359 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002360
2361 /* add special meaning first byte */
2362 if (buf) {
2363 buf = realloc(buf, word_len + 2);
2364 word = buf;
2365 } else {
2366 buf = malloc(word_len + 2);
2367 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002368 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002369 memmove(buf + 1, word, word_len + 1);
2370 word[0] = 0x06;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002371 restr->arg = lydict_insert_zc(ctx->ctx, word);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002372
2373 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002374 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002375
2376 switch (kw) {
2377 case YANG_DESCRIPTION:
2378 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts);
2379 break;
2380 case YANG_REFERENCE:
2381 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts);
2382 break;
2383 case YANG_ERROR_APP_TAG:
2384 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts);
2385 break;
2386 case YANG_ERROR_MESSAGE:
2387 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts);
2388 break;
2389 case YANG_MODIFIER:
2390 ret = parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts);
2391 break;
2392 case YANG_CUSTOM:
2393 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts);
2394 break;
2395 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002396 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002397 return LY_EVALID;
2398 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002399 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002400 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002401 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002402
2403 return ret;
2404}
2405
Michal Vaskoea5abea2018-09-18 13:10:54 +02002406/**
2407 * @brief Parse the type statement.
2408 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002409 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002410 * @param[in,out] data Data to read from, always moved to currently handled character.
2411 * @param[in,out] type Type to wrote to.
2412 *
2413 * @return LY_ERR values.
2414 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002415static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002416parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002417{
2418 LY_ERR ret = 0;
2419 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002420 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002421 enum yang_keyword kw;
2422 struct lysp_type *nest_type;
2423
2424 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002425 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002426 return LY_EVALID;
2427 }
2428
2429 /* get value */
2430 ret = get_string(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002431 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002432
Radek Krejci44ceedc2018-10-02 15:54:31 +02002433 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002434 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002435 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002436
2437 switch (kw) {
2438 case YANG_BASE:
2439 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts);
2440 break;
2441 case YANG_BIT:
2442 ret = parse_type_enum(ctx, data, kw, &type->bits);
2443 break;
2444 case YANG_ENUM:
2445 ret = parse_type_enum(ctx, data, kw, &type->enums);
2446 break;
2447 case YANG_FRACTION_DIGITS:
2448 ret = parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts);
2449 break;
2450 case YANG_LENGTH:
2451 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002452 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002453 return LY_EVALID;
2454 }
2455 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002456 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002457
2458 ret = parse_restr(ctx, data, kw, type->length);
2459 break;
2460 case YANG_PATH:
2461 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts);
2462 break;
2463 case YANG_PATTERN:
2464 ret = parse_type_pattern(ctx, data, &type->patterns);
2465 break;
2466 case YANG_RANGE:
2467 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002468 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002469 return LY_EVALID;
2470 }
2471 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002472 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002473
2474 ret = parse_restr(ctx, data, kw, type->range);
2475 break;
2476 case YANG_REQUIRE_INSTANCE:
2477 ret = parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts);
2478 break;
2479 case YANG_TYPE:
2480 {
2481 LYSP_ARRAY_NEW_RET(ctx, &type->types, nest_type, LY_EMEM);
2482 }
2483 ret = parse_type(ctx, data, nest_type);
2484 break;
2485 case YANG_CUSTOM:
2486 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts);
2487 break;
2488 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002489 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002490 return LY_EVALID;
2491 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002492 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002493 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002494 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002495
2496 return ret;
2497}
2498
Michal Vaskoea5abea2018-09-18 13:10:54 +02002499/**
2500 * @brief Parse the leaf statement.
2501 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002502 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002503 * @param[in,out] data Data to read from, always moved to currently handled character.
2504 * @param[in,out] siblings Siblings to add to.
2505 *
2506 * @return LY_ERR values.
2507 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002508static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002509parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002510{
2511 LY_ERR ret = 0;
2512 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002513 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002514 enum yang_keyword kw;
2515 struct lysp_node *iter;
2516 struct lysp_node_leaf *leaf;
2517
2518 /* create structure */
2519 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002520 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002521 leaf->nodetype = LYS_LEAF;
2522
2523 /* insert into siblings */
2524 if (!*siblings) {
2525 *siblings = (struct lysp_node *)leaf;
2526 } else {
2527 for (iter = *siblings; iter->next; iter = iter->next);
2528 iter->next = (struct lysp_node *)leaf;
2529 }
2530
2531 /* get name */
2532 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002533 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002534
Radek Krejci44ceedc2018-10-02 15:54:31 +02002535 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002536
2537 /* parse substatements */
2538 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002539 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002540
2541 switch (kw) {
2542 case YANG_CONFIG:
2543 ret = parse_config(ctx, data, &leaf->flags, &leaf->exts);
2544 break;
2545 case YANG_DEFAULT:
2546 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts);
2547 break;
2548 case YANG_DESCRIPTION:
2549 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts);
2550 break;
2551 case YANG_IF_FEATURE:
2552 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts);
2553 break;
2554 case YANG_MANDATORY:
2555 ret = parse_mandatory(ctx, data, &leaf->flags, &leaf->exts);
2556 break;
2557 case YANG_MUST:
2558 ret = parse_restrs(ctx, data, kw, &leaf->musts);
2559 break;
2560 case YANG_REFERENCE:
2561 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts);
2562 break;
2563 case YANG_STATUS:
2564 ret = parse_status(ctx, data, &leaf->flags, &leaf->exts);
2565 break;
2566 case YANG_TYPE:
2567 ret = parse_type(ctx, data, &leaf->type);
2568 break;
2569 case YANG_UNITS:
2570 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts);
2571 break;
2572 case YANG_WHEN:
2573 ret = parse_when(ctx, data, &leaf->when);
2574 break;
2575 case YANG_CUSTOM:
2576 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts);
2577 break;
2578 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002579 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002580 return LY_EVALID;
2581 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002582 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002583 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002584 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002585
2586 /* mandatory substatements */
2587 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002588 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002589 return LY_EVALID;
2590 }
2591
2592 return ret;
2593}
2594
Michal Vaskoea5abea2018-09-18 13:10:54 +02002595/**
2596 * @brief Parse the max-elements statement.
2597 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002598 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002599 * @param[in,out] data Data to read from, always moved to currently handled character.
2600 * @param[in,out] max Value to write to.
2601 * @param[in,out] flags Flags to write to.
2602 * @param[in,out] exts Extension instances to add to.
2603 *
2604 * @return LY_ERR values.
2605 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002606static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002607parse_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 +02002608{
2609 LY_ERR ret = 0;
2610 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002611 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002612 unsigned long int num;
2613 enum yang_keyword kw;
2614
2615 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002616 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002617 return LY_EVALID;
2618 }
2619 *flags |= LYS_SET_MAX;
2620
2621 /* get value */
2622 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002623 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002624
2625 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002626 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002627 free(buf);
2628 return LY_EVALID;
2629 }
2630
2631 if (strncmp(word, "unbounded", word_len)) {
2632 errno = 0;
2633 num = strtoul(word, &ptr, 10);
2634 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002635 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002636 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002637 free(buf);
2638 return LY_EVALID;
2639 }
2640 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002641 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002642 free(buf);
2643 return LY_EVALID;
2644 }
2645
2646 *max = num;
2647 }
2648 free(buf);
2649
2650 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002651 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002652
2653 switch (kw) {
2654 case YANG_CUSTOM:
2655 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002656 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002657 break;
2658 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002659 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002660 return LY_EVALID;
2661 }
2662 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002663 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002664
2665 return ret;
2666}
2667
Michal Vaskoea5abea2018-09-18 13:10:54 +02002668/**
2669 * @brief Parse the min-elements statement.
2670 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002671 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002672 * @param[in,out] data Data to read from, always moved to currently handled character.
2673 * @param[in,out] min Value to write to.
2674 * @param[in,out] flags Flags to write to.
2675 * @param[in,out] exts Extension instances to add to.
2676 *
2677 * @return LY_ERR values.
2678 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002679static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002680parse_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 +02002681{
2682 LY_ERR ret = 0;
2683 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002684 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002685 unsigned long int num;
2686 enum yang_keyword kw;
2687
2688 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002689 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002690 return LY_EVALID;
2691 }
2692 *flags |= LYS_SET_MIN;
2693
2694 /* get value */
2695 ret = get_string(ctx, data, Y_STR_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
2698 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002699 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002700 free(buf);
2701 return LY_EVALID;
2702 }
2703
2704 errno = 0;
2705 num = strtoul(word, &ptr, 10);
2706 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002707 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002708 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002709 free(buf);
2710 return LY_EVALID;
2711 }
2712 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002713 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002714 free(buf);
2715 return LY_EVALID;
2716 }
2717 *min = num;
2718 free(buf);
2719
2720 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002721 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002722
2723 switch (kw) {
2724 case YANG_CUSTOM:
2725 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002726 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002727 break;
2728 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002729 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002730 return LY_EVALID;
2731 }
2732 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002733 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002734
2735 return ret;
2736}
2737
Michal Vaskoea5abea2018-09-18 13:10:54 +02002738/**
2739 * @brief Parse the ordered-by statement.
2740 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002741 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002742 * @param[in,out] data Data to read from, always moved to currently handled character.
2743 * @param[in,out] flags Flags to write to.
2744 * @param[in,out] exts Extension instances to add to.
2745 *
2746 * @return LY_ERR values.
2747 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002748static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002749parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002750{
2751 LY_ERR ret = 0;
2752 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002753 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002754 enum yang_keyword kw;
2755
2756 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002757 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002758 return LY_EVALID;
2759 }
2760
2761 /* get value */
2762 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002763 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002764
2765 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2766 *flags |= LYS_ORDBY_SYSTEM;
2767 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2768 *flags |= LYS_ORDBY_USER;
2769 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002770 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002771 free(buf);
2772 return LY_EVALID;
2773 }
2774 free(buf);
2775
2776 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002777 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002778
2779 switch (kw) {
2780 case YANG_CUSTOM:
2781 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02002782 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002783 break;
2784 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002785 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002786 return LY_EVALID;
2787 }
2788 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002789 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002790
2791 return ret;
2792}
2793
Michal Vaskoea5abea2018-09-18 13:10:54 +02002794/**
2795 * @brief Parse the leaf-list statement.
2796 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002797 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002798 * @param[in,out] data Data to read from, always moved to currently handled character.
2799 * @param[in,out] siblings Siblings to add to.
2800 *
2801 * @return LY_ERR values.
2802 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002803static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002804parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002805{
2806 LY_ERR ret = 0;
2807 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002808 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002809 enum yang_keyword kw;
2810 struct lysp_node *iter;
2811 struct lysp_node_leaflist *llist;
2812
2813 /* create structure */
2814 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002815 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002816 llist->nodetype = LYS_LEAFLIST;
2817
2818 /* insert into siblings */
2819 if (!*siblings) {
2820 *siblings = (struct lysp_node *)llist;
2821 } else {
2822 for (iter = *siblings; iter->next; iter = iter->next);
2823 iter->next = (struct lysp_node *)llist;
2824 }
2825
2826 /* get name */
2827 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002828 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002829
Radek Krejci44ceedc2018-10-02 15:54:31 +02002830 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002831
2832 /* parse substatements */
2833 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002834 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002835
2836 switch (kw) {
2837 case YANG_CONFIG:
2838 ret = parse_config(ctx, data, &llist->flags, &llist->exts);
2839 break;
2840 case YANG_DEFAULT:
2841 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts);
2842 break;
2843 case YANG_DESCRIPTION:
2844 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts);
2845 break;
2846 case YANG_IF_FEATURE:
2847 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts);
2848 break;
2849 case YANG_MAX_ELEMENTS:
2850 ret = parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts);
2851 break;
2852 case YANG_MIN_ELEMENTS:
2853 ret = parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts);
2854 break;
2855 case YANG_MUST:
2856 ret = parse_restrs(ctx, data, kw, &llist->musts);
2857 break;
2858 case YANG_ORDERED_BY:
2859 ret = parse_orderedby(ctx, data, &llist->flags, &llist->exts);
2860 break;
2861 case YANG_REFERENCE:
2862 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts);
2863 break;
2864 case YANG_STATUS:
2865 ret = parse_status(ctx, data, &llist->flags, &llist->exts);
2866 break;
2867 case YANG_TYPE:
2868 ret = parse_type(ctx, data, &llist->type);
2869 break;
2870 case YANG_UNITS:
2871 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts);
2872 break;
2873 case YANG_WHEN:
2874 ret = parse_when(ctx, data, &llist->when);
2875 break;
2876 case YANG_CUSTOM:
2877 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts);
2878 break;
2879 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002880 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002881 return LY_EVALID;
2882 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002883 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002884 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002885 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002886
2887 /* mandatory substatements */
2888 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002889 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002890 return LY_EVALID;
2891 }
2892
2893 return ret;
2894}
2895
Michal Vaskoea5abea2018-09-18 13:10:54 +02002896/**
2897 * @brief Parse the refine statement.
2898 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002899 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002900 * @param[in,out] data Data to read from, always moved to currently handled character.
2901 * @param[in,out] refines Refines to add to.
2902 *
2903 * @return LY_ERR values.
2904 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002905static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002906parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002907{
2908 LY_ERR ret = 0;
2909 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002910 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002911 enum yang_keyword kw;
2912 struct lysp_refine *rf;
2913
2914 LYSP_ARRAY_NEW_RET(ctx, refines, rf, LY_EMEM);
2915
2916 /* get value */
2917 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002918 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002919
Radek Krejci44ceedc2018-10-02 15:54:31 +02002920 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002921 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002922 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002923
2924 switch (kw) {
2925 case YANG_CONFIG:
2926 ret = parse_config(ctx, data, &rf->flags, &rf->exts);
2927 break;
2928 case YANG_DEFAULT:
2929 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts);
2930 break;
2931 case YANG_DESCRIPTION:
2932 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts);
2933 break;
2934 case YANG_IF_FEATURE:
2935 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts);
2936 break;
2937 case YANG_MAX_ELEMENTS:
2938 ret = parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts);
2939 break;
2940 case YANG_MIN_ELEMENTS:
2941 ret = parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts);
2942 break;
2943 case YANG_MUST:
2944 ret = parse_restrs(ctx, data, kw, &rf->musts);
2945 break;
2946 case YANG_MANDATORY:
2947 ret = parse_mandatory(ctx, data, &rf->flags, &rf->exts);
2948 break;
2949 case YANG_REFERENCE:
2950 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts);
2951 break;
2952 case YANG_PRESENCE:
2953 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts);
2954 break;
2955 case YANG_CUSTOM:
2956 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts);
2957 break;
2958 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002959 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002960 return LY_EVALID;
2961 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002962 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002963 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002964 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002965
2966 return ret;
2967}
2968
Michal Vaskoea5abea2018-09-18 13:10:54 +02002969/**
2970 * @brief Parse the typedef statement.
2971 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002972 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002973 * @param[in,out] data Data to read from, always moved to currently handled character.
2974 * @param[in,out] typedefs Typedefs to add to.
2975 *
2976 * @return LY_ERR values.
2977 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002978static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002979parse_typedef(struct ly_parser_ctx *ctx, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002980{
2981 LY_ERR ret = 0;
2982 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002983 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002984 enum yang_keyword kw;
2985 struct lysp_tpdf *tpdf;
2986
2987 LYSP_ARRAY_NEW_RET(ctx, typedefs, tpdf, LY_EMEM);
2988
2989 /* get value */
2990 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02002991 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002992
Radek Krejci44ceedc2018-10-02 15:54:31 +02002993 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002994
2995 /* parse substatements */
2996 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02002997 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002998
2999 switch (kw) {
3000 case YANG_DEFAULT:
3001 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts);
3002 break;
3003 case YANG_DESCRIPTION:
3004 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts);
3005 break;
3006 case YANG_REFERENCE:
3007 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts);
3008 break;
3009 case YANG_STATUS:
3010 ret = parse_status(ctx, data, &tpdf->flags, &tpdf->exts);
3011 break;
3012 case YANG_TYPE:
3013 ret = parse_type(ctx, data, &tpdf->type);
3014 break;
3015 case YANG_UNITS:
3016 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts);
3017 break;
3018 case YANG_CUSTOM:
3019 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts);
3020 break;
3021 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003022 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003023 return LY_EVALID;
3024 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003025 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003026 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003027 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003028
3029 /* mandatory substatements */
3030 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003031 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003032 return LY_EVALID;
3033 }
3034
3035 return ret;
3036}
3037
Michal Vaskoea5abea2018-09-18 13:10:54 +02003038/**
3039 * @brief Parse the input or output statement.
3040 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003041 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003042 * @param[in,out] data Data to read from, always moved to currently handled character.
3043 * @param[in] kw Type of this particular keyword
3044 * @param[in,out] inout_p Input/output pointer to write to.
3045 *
3046 * @return LY_ERR values.
3047 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003048static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003049parse_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 +02003050{
3051 LY_ERR ret = 0;
3052 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003053 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003054 struct lysp_action_inout *inout;
3055
3056 if (*inout_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003057 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003058 return LY_EVALID;
3059 }
3060
3061 /* create structure */
3062 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003063 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003064 *inout_p = inout;
3065
3066 /* parse substatements */
3067 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003068 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003069
3070 switch (kw) {
3071 case YANG_ANYDATA:
3072 case YANG_ANYXML:
3073 ret = parse_any(ctx, data, kw, &inout->data);
3074 break;
3075 case YANG_CHOICE:
3076 ret = parse_choice(ctx, data, &inout->data);
3077 break;
3078 case YANG_CONTAINER:
3079 ret = parse_container(ctx, data, &inout->data);
3080 break;
3081 case YANG_LEAF:
3082 ret = parse_leaf(ctx, data, &inout->data);
3083 break;
3084 case YANG_LEAF_LIST:
3085 ret = parse_leaflist(ctx, data, &inout->data);
3086 break;
3087 case YANG_LIST:
3088 ret = parse_list(ctx, data, &inout->data);
3089 break;
3090 case YANG_USES:
3091 ret = parse_uses(ctx, data, &inout->data);
3092 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003093 case YANG_TYPEDEF:
3094 ret = parse_typedef(ctx, data, &inout->typedefs);
3095 break;
3096 case YANG_MUST:
3097 ret = parse_restrs(ctx, data, kw, &inout->musts);
3098 break;
3099 case YANG_GROUPING:
3100 ret = parse_grouping(ctx, data, &inout->groupings);
3101 break;
3102 case YANG_CUSTOM:
3103 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts);
3104 break;
3105 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003106 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "input/output");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003107 return LY_EVALID;
3108 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003109 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003110 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003111 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003112
3113 return ret;
3114}
3115
Michal Vaskoea5abea2018-09-18 13:10:54 +02003116/**
3117 * @brief Parse the action statement.
3118 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003119 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003120 * @param[in,out] data Data to read from, always moved to currently handled character.
3121 * @param[in,out] actions Actions to add to.
3122 *
3123 * @return LY_ERR values.
3124 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003125static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003126parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003127{
3128 LY_ERR ret = 0;
3129 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003130 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003131 enum yang_keyword kw;
3132 struct lysp_action *act;
3133
3134 LYSP_ARRAY_NEW_RET(ctx, actions, act, LY_EMEM);
3135
3136 /* get value */
3137 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003138 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003139
Radek Krejci44ceedc2018-10-02 15:54:31 +02003140 INSERT_WORD(ctx, buf, act->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003141 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003142 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003143
3144 switch (kw) {
3145 case YANG_DESCRIPTION:
3146 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts);
3147 break;
3148 case YANG_IF_FEATURE:
3149 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts);
3150 break;
3151 case YANG_REFERENCE:
3152 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts);
3153 break;
3154 case YANG_STATUS:
3155 ret = parse_status(ctx, data, &act->flags, &act->exts);
3156 break;
3157
3158 case YANG_INPUT:
3159 ret = parse_inout(ctx, data, kw, &act->input);
3160 break;
3161 case YANG_OUTPUT:
3162 ret = parse_inout(ctx, data, kw, &act->output);
3163 break;
3164
3165 case YANG_TYPEDEF:
3166 ret = parse_typedef(ctx, data, &act->typedefs);
3167 break;
3168 case YANG_GROUPING:
3169 ret = parse_grouping(ctx, data, &act->groupings);
3170 break;
3171 case YANG_CUSTOM:
3172 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts);
3173 break;
3174 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003175 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003176 return LY_EVALID;
3177 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003178 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003179 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003180 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003181
3182 return ret;
3183}
3184
Michal Vaskoea5abea2018-09-18 13:10:54 +02003185/**
3186 * @brief Parse the notification statement.
3187 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003188 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003189 * @param[in,out] data Data to read from, always moved to currently handled character.
3190 * @param[in,out] notifs Notifications to add to.
3191 *
3192 * @return LY_ERR values.
3193 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003194static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003195parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003196{
3197 LY_ERR ret = 0;
3198 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003199 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003200 enum yang_keyword kw;
3201 struct lysp_notif *notif;
3202
3203 LYSP_ARRAY_NEW_RET(ctx, notifs, notif, LY_EMEM);
3204
3205 /* get value */
3206 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003207 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003208
Radek Krejci44ceedc2018-10-02 15:54:31 +02003209 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003210 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003211 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003212
3213 switch (kw) {
3214 case YANG_DESCRIPTION:
3215 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts);
3216 break;
3217 case YANG_IF_FEATURE:
3218 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts);
3219 break;
3220 case YANG_REFERENCE:
3221 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts);
3222 break;
3223 case YANG_STATUS:
3224 ret = parse_status(ctx, data, &notif->flags, &notif->exts);
3225 break;
3226
3227 case YANG_ANYDATA:
3228 case YANG_ANYXML:
3229 ret = parse_any(ctx, data, kw, &notif->data);
3230 break;
3231 case YANG_CHOICE:
3232 ret = parse_case(ctx, data, &notif->data);
3233 break;
3234 case YANG_CONTAINER:
3235 ret = parse_container(ctx, data, &notif->data);
3236 break;
3237 case YANG_LEAF:
3238 ret = parse_leaf(ctx, data, &notif->data);
3239 break;
3240 case YANG_LEAF_LIST:
3241 ret = parse_leaflist(ctx, data, &notif->data);
3242 break;
3243 case YANG_LIST:
3244 ret = parse_list(ctx, data, &notif->data);
3245 break;
3246 case YANG_USES:
3247 ret = parse_uses(ctx, data, &notif->data);
3248 break;
3249
3250 case YANG_MUST:
3251 ret = parse_restrs(ctx, data, kw, &notif->musts);
3252 break;
3253 case YANG_TYPEDEF:
3254 ret = parse_typedef(ctx, data, &notif->typedefs);
3255 break;
3256 case YANG_GROUPING:
3257 ret = parse_grouping(ctx, data, &notif->groupings);
3258 break;
3259 case YANG_CUSTOM:
3260 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts);
3261 break;
3262 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003263 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003264 return LY_EVALID;
3265 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003266 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003267 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003268 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003269
3270 return ret;
3271}
3272
Michal Vaskoea5abea2018-09-18 13:10:54 +02003273/**
3274 * @brief Parse the grouping statement.
3275 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003276 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003277 * @param[in,out] data Data to read from, always moved to currently handled character.
3278 * @param[in,out] groupings Groupings to add to.
3279 *
3280 * @return LY_ERR values.
3281 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003282static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003283parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003284{
3285 LY_ERR ret = 0;
3286 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003287 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003288 enum yang_keyword kw;
3289 struct lysp_grp *grp;
3290
3291 LYSP_ARRAY_NEW_RET(ctx, groupings, grp, LY_EMEM);
3292
3293 /* get value */
3294 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003295 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003296
Radek Krejci44ceedc2018-10-02 15:54:31 +02003297 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003298
3299 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003300 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003301
3302 switch (kw) {
3303 case YANG_DESCRIPTION:
3304 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts);
3305 break;
3306 case YANG_REFERENCE:
3307 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts);
3308 break;
3309 case YANG_STATUS:
3310 ret = parse_status(ctx, data, &grp->flags, &grp->exts);
3311 break;
3312
3313 case YANG_ANYDATA:
3314 case YANG_ANYXML:
3315 ret = parse_any(ctx, data, kw, &grp->data);
3316 break;
3317 case YANG_CHOICE:
3318 ret = parse_choice(ctx, data, &grp->data);
3319 break;
3320 case YANG_CONTAINER:
3321 ret = parse_container(ctx, data, &grp->data);
3322 break;
3323 case YANG_LEAF:
3324 ret = parse_leaf(ctx, data, &grp->data);
3325 break;
3326 case YANG_LEAF_LIST:
3327 ret = parse_leaflist(ctx, data, &grp->data);
3328 break;
3329 case YANG_LIST:
3330 ret = parse_list(ctx, data, &grp->data);
3331 break;
3332 case YANG_USES:
3333 ret = parse_uses(ctx, data, &grp->data);
3334 break;
3335
3336 case YANG_TYPEDEF:
3337 ret = parse_typedef(ctx, data, &grp->typedefs);
3338 break;
3339 case YANG_ACTION:
3340 ret = parse_action(ctx, data, &grp->actions);
3341 break;
3342 case YANG_GROUPING:
3343 ret = parse_grouping(ctx, data, &grp->groupings);
3344 break;
3345 case YANG_NOTIFICATION:
3346 ret = parse_notif(ctx, data, &grp->notifs);
3347 break;
3348 case YANG_CUSTOM:
3349 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts);
3350 break;
3351 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003352 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003353 return LY_EVALID;
3354 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003355 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003356 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003357 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003358
3359 return ret;
3360}
3361
Michal Vaskoea5abea2018-09-18 13:10:54 +02003362/**
3363 * @brief Parse the refine statement.
3364 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003365 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003366 * @param[in,out] data Data to read from, always moved to currently handled character.
3367 * @param[in,out] augments Augments to add to.
3368 *
3369 * @return LY_ERR values.
3370 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003371static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003372parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003373{
3374 LY_ERR ret = 0;
3375 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003376 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003377 enum yang_keyword kw;
3378 struct lysp_augment *aug;
3379
3380 LYSP_ARRAY_NEW_RET(ctx, augments, aug, LY_EMEM);
3381
3382 /* get value */
3383 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003384 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003385
Radek Krejci44ceedc2018-10-02 15:54:31 +02003386 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003387 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003388 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003389
3390 switch (kw) {
3391 case YANG_DESCRIPTION:
3392 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts);
3393 break;
3394 case YANG_IF_FEATURE:
3395 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts);
3396 break;
3397 case YANG_REFERENCE:
3398 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts);
3399 break;
3400 case YANG_STATUS:
3401 ret = parse_status(ctx, data, &aug->flags, &aug->exts);
3402 break;
3403 case YANG_WHEN:
3404 ret = parse_when(ctx, data, &aug->when);
3405 break;
3406
3407 case YANG_ANYDATA:
3408 case YANG_ANYXML:
3409 ret = parse_any(ctx, data, kw, &aug->child);
3410 break;
3411 case YANG_CASE:
3412 ret = parse_case(ctx, data, &aug->child);
3413 break;
3414 case YANG_CHOICE:
3415 ret = parse_choice(ctx, data, &aug->child);
3416 break;
3417 case YANG_CONTAINER:
3418 ret = parse_container(ctx, data, &aug->child);
3419 break;
3420 case YANG_LEAF:
3421 ret = parse_leaf(ctx, data, &aug->child);
3422 break;
3423 case YANG_LEAF_LIST:
3424 ret = parse_leaflist(ctx, data, &aug->child);
3425 break;
3426 case YANG_LIST:
3427 ret = parse_list(ctx, data, &aug->child);
3428 break;
3429 case YANG_USES:
3430 ret = parse_uses(ctx, data, &aug->child);
3431 break;
3432
3433 case YANG_ACTION:
3434 ret = parse_action(ctx, data, &aug->actions);
3435 break;
3436 case YANG_NOTIFICATION:
3437 ret = parse_notif(ctx, data, &aug->notifs);
3438 break;
3439 case YANG_CUSTOM:
3440 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts);
3441 break;
3442 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003443 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003444 return LY_EVALID;
3445 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003446 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003447 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003448 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003449
3450 return ret;
3451}
3452
Michal Vaskoea5abea2018-09-18 13:10:54 +02003453/**
3454 * @brief Parse the uses statement.
3455 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003456 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003457 * @param[in,out] data Data to read from, always moved to currently handled character.
3458 * @param[in,out] siblings Siblings to add to.
3459 *
3460 * @return LY_ERR values.
3461 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003462static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003463parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003464{
3465 LY_ERR ret = 0;
3466 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003467 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003468 enum yang_keyword kw;
3469 struct lysp_node *iter;
3470 struct lysp_node_uses *uses;
3471
3472 /* create structure */
3473 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003474 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003475 uses->nodetype = LYS_USES;
3476
3477 /* insert into siblings */
3478 if (!*siblings) {
3479 *siblings = (struct lysp_node *)uses;
3480 } else {
3481 for (iter = *siblings; iter->next; iter = iter->next);
3482 iter->next = (struct lysp_node *)uses;
3483 }
3484
3485 /* get name */
3486 ret = get_string(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003487 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003488
Radek Krejci44ceedc2018-10-02 15:54:31 +02003489 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003490
3491 /* parse substatements */
3492 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003493 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003494
3495 switch (kw) {
3496 case YANG_DESCRIPTION:
3497 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts);
3498 break;
3499 case YANG_IF_FEATURE:
3500 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts);
3501 break;
3502 case YANG_REFERENCE:
3503 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts);
3504 break;
3505 case YANG_STATUS:
3506 ret = parse_status(ctx, data, &uses->flags, &uses->exts);
3507 break;
3508 case YANG_WHEN:
3509 ret = parse_when(ctx, data, &uses->when);
3510 break;
3511
3512 case YANG_REFINE:
3513 ret = parse_refine(ctx, data, &uses->refines);
3514 break;
3515 case YANG_AUGMENT:
3516 ret = parse_augment(ctx, data, &uses->augments);
3517 break;
3518 case YANG_CUSTOM:
3519 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts);
3520 break;
3521 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003522 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003523 return LY_EVALID;
3524 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003525 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003526 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003527 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003528
3529 return ret;
3530}
3531
Michal Vaskoea5abea2018-09-18 13:10:54 +02003532/**
3533 * @brief Parse the case statement.
3534 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003535 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003536 * @param[in,out] data Data to read from, always moved to currently handled character.
3537 * @param[in,out] siblings Siblings to add to.
3538 *
3539 * @return LY_ERR values.
3540 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003541static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003542parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543{
3544 LY_ERR ret = 0;
3545 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003546 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003547 enum yang_keyword kw;
3548 struct lysp_node *iter;
3549 struct lysp_node_case *cas;
3550
3551 /* create structure */
3552 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003553 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003554 cas->nodetype = LYS_CASE;
3555
3556 /* insert into siblings */
3557 if (!*siblings) {
3558 *siblings = (struct lysp_node *)cas;
3559 } else {
3560 for (iter = *siblings; iter->next; iter = iter->next);
3561 iter->next = (struct lysp_node *)cas;
3562 }
3563
3564 /* get name */
3565 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003566 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003567
Radek Krejci44ceedc2018-10-02 15:54:31 +02003568 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003569
3570 /* parse substatements */
3571 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003572 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003573
3574 switch (kw) {
3575 case YANG_DESCRIPTION:
3576 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts);
3577 break;
3578 case YANG_IF_FEATURE:
3579 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts);
3580 break;
3581 case YANG_REFERENCE:
3582 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts);
3583 break;
3584 case YANG_STATUS:
3585 ret = parse_status(ctx, data, &cas->flags, &cas->exts);
3586 break;
3587 case YANG_WHEN:
3588 ret = parse_when(ctx, data, &cas->when);
3589 break;
3590
3591 case YANG_ANYDATA:
3592 case YANG_ANYXML:
3593 ret = parse_any(ctx, data, kw, &cas->child);
3594 break;
3595 case YANG_CHOICE:
3596 ret = parse_case(ctx, data, &cas->child);
3597 break;
3598 case YANG_CONTAINER:
3599 ret = parse_container(ctx, data, &cas->child);
3600 break;
3601 case YANG_LEAF:
3602 ret = parse_leaf(ctx, data, &cas->child);
3603 break;
3604 case YANG_LEAF_LIST:
3605 ret = parse_leaflist(ctx, data, &cas->child);
3606 break;
3607 case YANG_LIST:
3608 ret = parse_list(ctx, data, &cas->child);
3609 break;
3610 case YANG_USES:
3611 ret = parse_uses(ctx, data, &cas->child);
3612 break;
3613 case YANG_CUSTOM:
3614 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts);
3615 break;
3616 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003617 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003618 return LY_EVALID;
3619 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003620 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003621 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003622 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003623
3624 return ret;
3625}
3626
Michal Vaskoea5abea2018-09-18 13:10:54 +02003627/**
3628 * @brief Parse the choice statement.
3629 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003630 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003631 * @param[in,out] data Data to read from, always moved to currently handled character.
3632 * @param[in,out] siblings Siblings to add to.
3633 *
3634 * @return LY_ERR values.
3635 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003636static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003637parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003638{
3639 LY_ERR ret = 0;
3640 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003641 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003642 enum yang_keyword kw;
3643 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003644 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003645
3646 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003647 choice = calloc(1, sizeof *choice);
3648 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3649 choice->nodetype = LYS_CHOICE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003650
3651 /* insert into siblings */
3652 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003653 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003654 } else {
3655 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003656 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003657 }
3658
3659 /* get name */
3660 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003661 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003662
Radek Krejci44ceedc2018-10-02 15:54:31 +02003663 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003664
3665 /* parse substatements */
3666 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003667 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003668
3669 switch (kw) {
3670 case YANG_CONFIG:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003671 ret = parse_config(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003672 break;
3673 case YANG_DESCRIPTION:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003674 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003675 break;
3676 case YANG_IF_FEATURE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003677 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003678 break;
3679 case YANG_MANDATORY:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003680 ret = parse_mandatory(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003681 break;
3682 case YANG_REFERENCE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003683 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003684 break;
3685 case YANG_STATUS:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003686 ret = parse_status(ctx, data, &choice->flags, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003687 break;
3688 case YANG_WHEN:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003689 ret = parse_when(ctx, data, &choice->when);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003690 break;
3691 case YANG_DEFAULT:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003692 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_IDENTIF_ARG, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003693 break;
3694
3695 case YANG_ANYDATA:
3696 case YANG_ANYXML:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003697 ret = parse_any(ctx, data, kw, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003698 break;
3699 case YANG_CASE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003700 ret = parse_case(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003701 break;
3702 case YANG_CHOICE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003703 ret = parse_choice(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003704 break;
3705 case YANG_CONTAINER:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003706 ret = parse_container(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003707 break;
3708 case YANG_LEAF:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003709 ret = parse_leaf(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003710 break;
3711 case YANG_LEAF_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003712 ret = parse_leaflist(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003713 break;
3714 case YANG_LIST:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003715 ret = parse_list(ctx, data, &choice->child);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003716 break;
3717 case YANG_CUSTOM:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003718 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003719 break;
3720 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003721 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003722 return LY_EVALID;
3723 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003724 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003725 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003726 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003727
3728 return ret;
3729}
3730
Michal Vaskoea5abea2018-09-18 13:10:54 +02003731/**
3732 * @brief Parse the container statement.
3733 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003734 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003735 * @param[in,out] data Data to read from, always moved to currently handled character.
3736 * @param[in,out] siblings Siblings to add to.
3737 *
3738 * @return LY_ERR values.
3739 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003740static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003741parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003742{
3743 LY_ERR ret = 0;
3744 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003745 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003746 enum yang_keyword kw;
3747 struct lysp_node *iter;
3748 struct lysp_node_container *cont;
3749
3750 /* create structure */
3751 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003752 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003753 cont->nodetype = LYS_CONTAINER;
3754
3755 /* insert into siblings */
3756 if (!*siblings) {
3757 *siblings = (struct lysp_node *)cont;
3758 } else {
3759 for (iter = *siblings; iter->next; iter = iter->next);
3760 iter->next = (struct lysp_node *)cont;
3761 }
3762
3763 /* get name */
3764 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003765 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003766
Radek Krejci44ceedc2018-10-02 15:54:31 +02003767 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003768
3769 /* parse substatements */
3770 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003771 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003772
3773 switch (kw) {
3774 case YANG_CONFIG:
3775 ret = parse_config(ctx, data, &cont->flags, &cont->exts);
3776 break;
3777 case YANG_DESCRIPTION:
3778 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts);
3779 break;
3780 case YANG_IF_FEATURE:
3781 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts);
3782 break;
3783 case YANG_REFERENCE:
3784 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts);
3785 break;
3786 case YANG_STATUS:
3787 ret = parse_status(ctx, data, &cont->flags, &cont->exts);
3788 break;
3789 case YANG_WHEN:
3790 ret = parse_when(ctx, data, &cont->when);
3791 break;
3792 case YANG_PRESENCE:
3793 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts);
3794 break;
3795
3796 case YANG_ANYDATA:
3797 case YANG_ANYXML:
3798 ret = parse_any(ctx, data, kw, &cont->child);
3799 break;
3800 case YANG_CHOICE:
3801 ret = parse_choice(ctx, data, &cont->child);
3802 break;
3803 case YANG_CONTAINER:
3804 ret = parse_container(ctx, data, &cont->child);
3805 break;
3806 case YANG_LEAF:
3807 ret = parse_leaf(ctx, data, &cont->child);
3808 break;
3809 case YANG_LEAF_LIST:
3810 ret = parse_leaflist(ctx, data, &cont->child);
3811 break;
3812 case YANG_LIST:
3813 ret = parse_list(ctx, data, &cont->child);
3814 break;
3815 case YANG_USES:
3816 ret = parse_uses(ctx, data, &cont->child);
3817 break;
3818
3819 case YANG_TYPEDEF:
3820 ret = parse_typedef(ctx, data, &cont->typedefs);
3821 break;
3822 case YANG_MUST:
3823 ret = parse_restrs(ctx, data, kw, &cont->musts);
3824 break;
3825 case YANG_ACTION:
3826 ret = parse_action(ctx, data, &cont->actions);
3827 break;
3828 case YANG_GROUPING:
3829 ret = parse_grouping(ctx, data, &cont->groupings);
3830 break;
3831 case YANG_NOTIFICATION:
3832 ret = parse_notif(ctx, data, &cont->notifs);
3833 break;
3834 case YANG_CUSTOM:
3835 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts);
3836 break;
3837 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003838 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003839 return LY_EVALID;
3840 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003841 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003842 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003843 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003844
3845 return ret;
3846}
3847
Michal Vaskoea5abea2018-09-18 13:10:54 +02003848/**
3849 * @brief Parse the list statement.
3850 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003851 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003852 * @param[in,out] data Data to read from, always moved to currently handled character.
3853 * @param[in,out] siblings Siblings to add to.
3854 *
3855 * @return LY_ERR values.
3856 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003857static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003858parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003859{
3860 LY_ERR ret = 0;
3861 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003862 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003863 enum yang_keyword kw;
3864 struct lysp_node *iter;
3865 struct lysp_node_list *list;
3866
3867 /* create structure */
3868 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003869 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003870 list->nodetype = LYS_LIST;
3871
3872 /* insert into siblings */
3873 if (!*siblings) {
3874 *siblings = (struct lysp_node *)list;
3875 } else {
3876 for (iter = *siblings; iter->next; iter = iter->next);
3877 iter->next = (struct lysp_node *)list;
3878 }
3879
3880 /* get name */
3881 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02003882 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003883
Radek Krejci44ceedc2018-10-02 15:54:31 +02003884 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003885
3886 /* parse substatements */
3887 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02003888 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003889
3890 switch (kw) {
3891 case YANG_CONFIG:
3892 ret = parse_config(ctx, data, &list->flags, &list->exts);
3893 break;
3894 case YANG_DESCRIPTION:
3895 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts);
3896 break;
3897 case YANG_IF_FEATURE:
3898 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts);
3899 break;
3900 case YANG_REFERENCE:
3901 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts);
3902 break;
3903 case YANG_STATUS:
3904 ret = parse_status(ctx, data, &list->flags, &list->exts);
3905 break;
3906 case YANG_WHEN:
3907 ret = parse_when(ctx, data, &list->when);
3908 break;
3909 case YANG_KEY:
3910 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts);
3911 break;
3912 case YANG_MAX_ELEMENTS:
3913 ret = parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts);
3914 break;
3915 case YANG_MIN_ELEMENTS:
3916 ret = parse_minelements(ctx, data, &list->min, &list->flags, &list->exts);
3917 break;
3918 case YANG_ORDERED_BY:
3919 ret = parse_orderedby(ctx, data, &list->flags, &list->exts);
3920 break;
3921 case YANG_UNIQUE:
3922 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts);
3923 break;
3924
3925 case YANG_ANYDATA:
3926 case YANG_ANYXML:
3927 ret = parse_any(ctx, data, kw, &list->child);
3928 break;
3929 case YANG_CHOICE:
3930 ret = parse_choice(ctx, data, &list->child);
3931 break;
3932 case YANG_CONTAINER:
3933 ret = parse_container(ctx, data, &list->child);
3934 break;
3935 case YANG_LEAF:
3936 ret = parse_leaf(ctx, data, &list->child);
3937 break;
3938 case YANG_LEAF_LIST:
3939 ret = parse_leaflist(ctx, data, &list->child);
3940 break;
3941 case YANG_LIST:
3942 ret = parse_list(ctx, data, &list->child);
3943 break;
3944 case YANG_USES:
3945 ret = parse_uses(ctx, data, &list->child);
3946 break;
3947
3948 case YANG_TYPEDEF:
3949 ret = parse_typedef(ctx, data, &list->typedefs);
3950 break;
3951 case YANG_MUST:
3952 ret = parse_restrs(ctx, data, kw, &list->musts);
3953 break;
3954 case YANG_ACTION:
3955 ret = parse_action(ctx, data, &list->actions);
3956 break;
3957 case YANG_GROUPING:
3958 ret = parse_grouping(ctx, data, &list->groupings);
3959 break;
3960 case YANG_NOTIFICATION:
3961 ret = parse_notif(ctx, data, &list->notifs);
3962 break;
3963 case YANG_CUSTOM:
3964 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts);
3965 break;
3966 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003967 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003968 return LY_EVALID;
3969 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003970 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003971 }
Radek Krejcic59bc972018-09-17 16:13:06 +02003972 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003973
3974 return ret;
3975}
3976
Michal Vaskoea5abea2018-09-18 13:10:54 +02003977/**
3978 * @brief Parse the yin-element statement.
3979 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003980 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003981 * @param[in,out] data Data to read from, always moved to currently handled character.
3982 * @param[in,out] flags Flags to write to.
3983 * @param[in,out] exts Extension instances to add to.
3984 *
3985 * @return LY_ERR values.
3986 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003987static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003988parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003989{
3990 LY_ERR ret = 0;
3991 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003992 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003993 enum yang_keyword kw;
3994
3995 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003996 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003997 return LY_EVALID;
3998 }
3999
4000 /* get value */
4001 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004002 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004003
4004 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
4005 *flags |= LYS_YINELEM_TRUE;
4006 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
4007 *flags |= LYS_YINELEM_FALSE;
4008 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004009 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004010 free(buf);
4011 return LY_EVALID;
4012 }
4013 free(buf);
4014
4015 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004016 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004017
4018 switch (kw) {
4019 case YANG_CUSTOM:
4020 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts);
Radek Krejcic59bc972018-09-17 16:13:06 +02004021 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004022 break;
4023 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004024 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004025 return LY_EVALID;
4026 }
4027 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004028 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004029
4030 return ret;
4031}
4032
Michal Vaskoea5abea2018-09-18 13:10:54 +02004033/**
4034 * @brief Parse the yin-element statement.
4035 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004036 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004037 * @param[in,out] data Data to read from, always moved to currently handled character.
4038 * @param[in,out] argument Value to write to.
4039 * @param[in,out] flags Flags to write to.
4040 * @param[in,out] exts Extension instances to add to.
4041 *
4042 * @return LY_ERR values.
4043 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004044static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004045parse_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 +02004046{
4047 LY_ERR ret = 0;
4048 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004049 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004050 enum yang_keyword kw;
4051
4052 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004053 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004054 return LY_EVALID;
4055 }
4056
4057 /* get value */
4058 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004059 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004060
Radek Krejci44ceedc2018-10-02 15:54:31 +02004061 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004062 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004063 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004064
4065 switch (kw) {
4066 case YANG_YIN_ELEMENT:
4067 ret = parse_yinelement(ctx, data, flags, exts);
4068 break;
4069 case YANG_CUSTOM:
4070 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts);
4071 break;
4072 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004073 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004074 return LY_EVALID;
4075 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004076 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004077 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004078 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004079
4080 return ret;
4081}
4082
Michal Vaskoea5abea2018-09-18 13:10:54 +02004083/**
4084 * @brief Parse the extension statement.
4085 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004086 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004087 * @param[in,out] data Data to read from, always moved to currently handled character.
4088 * @param[in,out] extensions Extensions to add to.
4089 *
4090 * @return LY_ERR values.
4091 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004092static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004093parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004094{
4095 LY_ERR ret = 0;
4096 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004097 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004098 enum yang_keyword kw;
4099 struct lysp_ext *ex;
4100
4101 LYSP_ARRAY_NEW_RET(ctx, extensions, ex, LY_EMEM);
4102
4103 /* get value */
4104 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004105 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004106
Radek Krejci44ceedc2018-10-02 15:54:31 +02004107 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004108 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004109 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004110
4111 switch (kw) {
4112 case YANG_DESCRIPTION:
4113 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts);
4114 break;
4115 case YANG_REFERENCE:
4116 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts);
4117 break;
4118 case YANG_STATUS:
4119 ret = parse_status(ctx, data, &ex->flags, &ex->exts);
4120 break;
4121 case YANG_ARGUMENT:
4122 ret = parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts);
4123 break;
4124 case YANG_CUSTOM:
4125 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts);
4126 break;
4127 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004128 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004129 return LY_EVALID;
4130 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004131 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004132 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004133 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004134
4135 return ret;
4136}
4137
Michal Vaskoea5abea2018-09-18 13:10:54 +02004138/**
4139 * @brief Parse the deviate statement.
4140 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004141 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004142 * @param[in,out] data Data to read from, always moved to currently handled character.
4143 * @param[in,out] deviates Deviates to add to.
4144 *
4145 * @return LY_ERR values.
4146 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004147static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004148parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004149{
4150 LY_ERR ret = 0;
4151 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004152 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004153 enum yang_keyword kw;
4154 struct lysp_deviate *iter, *d;
4155 struct lysp_deviate_add *d_add = NULL;
4156 struct lysp_deviate_rpl *d_rpl = NULL;
4157 struct lysp_deviate_del *d_del = NULL;
4158 const char **d_units, ***d_uniques, ***d_dflts;
4159 struct lysp_restr **d_musts;
4160 uint16_t *d_flags;
4161 uint32_t *d_min, *d_max;
4162
4163 /* get value */
4164 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004165 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004166
4167 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
4168 dev_mod = LYS_DEV_NOT_SUPPORTED;
4169 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
4170 dev_mod = LYS_DEV_ADD;
4171 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
4172 dev_mod = LYS_DEV_REPLACE;
4173 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
4174 dev_mod = LYS_DEV_DELETE;
4175 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004176 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004177 free(buf);
4178 return LY_EVALID;
4179 }
4180 free(buf);
4181
4182 /* create structure */
4183 switch (dev_mod) {
4184 case LYS_DEV_NOT_SUPPORTED:
4185 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004186 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004187 break;
4188 case LYS_DEV_ADD:
4189 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004190 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004191 d = (struct lysp_deviate *)d_add;
4192 d_units = &d_add->units;
4193 d_uniques = &d_add->uniques;
4194 d_dflts = &d_add->dflts;
4195 d_musts = &d_add->musts;
4196 d_flags = &d_add->flags;
4197 d_min = &d_add->min;
4198 d_max = &d_add->max;
4199 break;
4200 case LYS_DEV_REPLACE:
4201 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004202 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004203 d = (struct lysp_deviate *)d_rpl;
4204 d_units = &d_rpl->units;
4205 d_flags = &d_rpl->flags;
4206 d_min = &d_rpl->min;
4207 d_max = &d_rpl->max;
4208 break;
4209 case LYS_DEV_DELETE:
4210 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004211 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004212 d = (struct lysp_deviate *)d_del;
4213 d_units = &d_del->units;
4214 d_uniques = &d_del->uniques;
4215 d_dflts = &d_del->dflts;
4216 d_musts = &d_del->musts;
4217 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004218 break;
4219 default:
4220 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004221 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004222 }
4223 d->mod = dev_mod;
4224
4225 /* insert into siblings */
4226 if (!*deviates) {
4227 *deviates = d;
4228 } else {
4229 for (iter = *deviates; iter->next; iter = iter->next);
4230 iter->next = d;
4231 }
4232
4233 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004234 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004235
4236 switch (kw) {
4237 case YANG_CONFIG:
4238 switch (dev_mod) {
4239 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004240 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004241 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004242 return LY_EVALID;
4243 default:
4244 ret = parse_config(ctx, data, d_flags, &d->exts);
4245 break;
4246 }
4247 break;
4248 case YANG_DEFAULT:
4249 switch (dev_mod) {
4250 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004251 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004252 return LY_EVALID;
4253 case LYS_DEV_REPLACE:
4254 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts);
4255 break;
4256 default:
4257 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts);
4258 break;
4259 }
4260 break;
4261 case YANG_MANDATORY:
4262 switch (dev_mod) {
4263 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004264 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004265 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004266 return LY_EVALID;
4267 default:
4268 ret = parse_mandatory(ctx, data, d_flags, &d->exts);
4269 break;
4270 }
4271 break;
4272 case YANG_MAX_ELEMENTS:
4273 switch (dev_mod) {
4274 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004275 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004276 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004277 return LY_EVALID;
4278 default:
4279 ret = parse_maxelements(ctx, data, d_max, d_flags, &d->exts);
4280 break;
4281 }
4282 break;
4283 case YANG_MIN_ELEMENTS:
4284 switch (dev_mod) {
4285 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004286 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004287 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004288 return LY_EVALID;
4289 default:
4290 ret = parse_minelements(ctx, data, d_min, d_flags, &d->exts);
4291 break;
4292 }
4293 break;
4294 case YANG_MUST:
4295 switch (dev_mod) {
4296 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004297 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004298 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004299 return LY_EVALID;
4300 default:
4301 ret = parse_restrs(ctx, data, kw, d_musts);
4302 break;
4303 }
4304 break;
4305 case YANG_TYPE:
4306 switch (dev_mod) {
4307 case LYS_DEV_NOT_SUPPORTED:
4308 case LYS_DEV_ADD:
4309 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004310 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004311 return LY_EVALID;
4312 default:
4313 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004314 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004315 ret = parse_type(ctx, data, d_rpl->type);
4316 break;
4317 }
4318 break;
4319 case YANG_UNIQUE:
4320 switch (dev_mod) {
4321 case LYS_DEV_NOT_SUPPORTED:
4322 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004323 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004324 return LY_EVALID;
4325 default:
4326 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts);
4327 break;
4328 }
4329 break;
4330 case YANG_UNITS:
4331 switch (dev_mod) {
4332 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004333 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004334 return LY_EVALID;
4335 default:
4336 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts);
4337 break;
4338 }
4339 break;
4340 case YANG_CUSTOM:
4341 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts);
4342 break;
4343 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004344 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004345 return LY_EVALID;
4346 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004347 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004348 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004349 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004350
4351 return ret;
4352}
4353
Michal Vaskoea5abea2018-09-18 13:10:54 +02004354/**
4355 * @brief Parse the deviation statement.
4356 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004357 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004358 * @param[in,out] data Data to read from, always moved to currently handled character.
4359 * @param[in,out] deviations Deviations to add to.
4360 *
4361 * @return LY_ERR values.
4362 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004363static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004364parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004365{
4366 LY_ERR ret = 0;
4367 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004368 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004369 enum yang_keyword kw;
4370 struct lysp_deviation *dev;
4371
4372 LYSP_ARRAY_NEW_RET(ctx, deviations, dev, LY_EMEM);
4373
4374 /* get value */
4375 ret = get_string(ctx, data, Y_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004376 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004377
Radek Krejci44ceedc2018-10-02 15:54:31 +02004378 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004379 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004380 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004381
4382 switch (kw) {
4383 case YANG_DESCRIPTION:
4384 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts);
4385 break;
4386 case YANG_DEVIATE:
4387 ret = parse_deviate(ctx, data, &dev->deviates);
4388 break;
4389 case YANG_REFERENCE:
4390 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts);
4391 break;
4392 case YANG_CUSTOM:
4393 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts);
4394 break;
4395 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004396 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004397 return LY_EVALID;
4398 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004399 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004400 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004401 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004402
4403 /* mandatory substatements */
4404 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004405 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004406 return LY_EVALID;
4407 }
4408
4409 return ret;
4410}
4411
Michal Vaskoea5abea2018-09-18 13:10:54 +02004412/**
4413 * @brief Parse the feature statement.
4414 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004415 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004416 * @param[in,out] data Data to read from, always moved to currently handled character.
4417 * @param[in,out] features Features to add to.
4418 *
4419 * @return LY_ERR values.
4420 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004421static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004422parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004423{
4424 LY_ERR ret = 0;
4425 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004426 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004427 enum yang_keyword kw;
4428 struct lysp_feature *feat;
4429
4430 LYSP_ARRAY_NEW_RET(ctx, features, feat, LY_EMEM);
4431
4432 /* get value */
4433 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004434 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004435
Radek Krejci44ceedc2018-10-02 15:54:31 +02004436 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004437 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004438 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004439
4440 switch (kw) {
4441 case YANG_DESCRIPTION:
4442 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts);
4443 break;
4444 case YANG_IF_FEATURE:
4445 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts);
4446 break;
4447 case YANG_REFERENCE:
4448 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts);
4449 break;
4450 case YANG_STATUS:
4451 ret = parse_status(ctx, data, &feat->flags, &feat->exts);
4452 break;
4453 case YANG_CUSTOM:
4454 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts);
4455 break;
4456 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004457 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004458 return LY_EMEM;
4459 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004460 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004461 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004462 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004463
4464 return ret;
4465}
4466
Michal Vaskoea5abea2018-09-18 13:10:54 +02004467/**
4468 * @brief Parse the identity statement.
4469 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004470 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004471 * @param[in,out] data Data to read from, always moved to currently handled character.
4472 * @param[in,out] identities Identities to add to.
4473 *
4474 * @return LY_ERR values.
4475 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004476static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004477parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004478{
4479 LY_ERR ret = 0;
4480 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004481 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004482 enum yang_keyword kw;
4483 struct lysp_ident *ident;
4484
4485 LYSP_ARRAY_NEW_RET(ctx, identities, ident, LY_EMEM);
4486
4487 /* get value */
4488 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004489 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004490
Radek Krejci44ceedc2018-10-02 15:54:31 +02004491 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004492 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004493 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004494
4495 switch (kw) {
4496 case YANG_DESCRIPTION:
4497 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts);
4498 break;
4499 case YANG_IF_FEATURE:
4500 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts);
4501 break;
4502 case YANG_REFERENCE:
4503 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts);
4504 break;
4505 case YANG_STATUS:
4506 ret = parse_status(ctx, data, &ident->flags, &ident->exts);
4507 break;
4508 case YANG_BASE:
4509 ret = parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts);
4510 break;
4511 case YANG_CUSTOM:
4512 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts);
4513 break;
4514 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004515 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004516 return LY_EVALID;
4517 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004518 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004519 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004520 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004521
4522 return ret;
4523}
4524
Michal Vaskoea5abea2018-09-18 13:10:54 +02004525/**
4526 * @brief Parse the module or submodule statement.
4527 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004528 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004529 * @param[in,out] data Data to read from, always moved to currently handled character.
4530 * @param[in,out] mod Module to write to.
4531 *
4532 * @return LY_ERR values.
4533 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004534static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004535parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004536{
4537 LY_ERR ret = 0;
4538 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004539 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004540 enum yang_keyword kw, prev_kw = 0;
4541 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
4542
4543 /* (sub)module name */
4544 ret = get_string(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004545 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004546
Radek Krejci44ceedc2018-10-02 15:54:31 +02004547 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004548 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
Radek Krejcic59bc972018-09-17 16:13:06 +02004549 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004550
4551 switch (kw) {
4552 /* module header */
4553 case YANG_NAMESPACE:
4554 case YANG_PREFIX:
4555 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004556 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004557 return LY_EVALID;
4558 }
4559 /* fallthrough */
4560 case YANG_BELONGS_TO:
4561 if ((kw == YANG_BELONGS_TO) && !mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004562 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004563 return LY_EVALID;
4564 }
4565 /* fallthrough */
4566 case YANG_YANG_VERSION:
4567 if (mod_stmt > Y_MOD_MODULE_HEADER) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004568 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004569 return LY_EVALID;
4570 }
4571 break;
4572 /* linkage */
4573 case YANG_INCLUDE:
4574 case YANG_IMPORT:
4575 if (mod_stmt > Y_MOD_LINKAGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004576 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004577 return LY_EVALID;
4578 }
4579 mod_stmt = Y_MOD_LINKAGE;
4580 break;
4581 /* meta */
4582 case YANG_ORGANIZATION:
4583 case YANG_CONTACT:
4584 case YANG_DESCRIPTION:
4585 case YANG_REFERENCE:
4586 if (mod_stmt > Y_MOD_META) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004587 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004588 return LY_EVALID;
4589 }
4590 mod_stmt = Y_MOD_META;
4591 break;
4592
4593 /* revision */
4594 case YANG_REVISION:
4595 if (mod_stmt > Y_MOD_REVISION) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004596 LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004597 return LY_EVALID;
4598 }
4599 mod_stmt = Y_MOD_REVISION;
4600 break;
4601
4602 /* body */
4603 case YANG_ANYDATA:
4604 case YANG_ANYXML:
4605 case YANG_AUGMENT:
4606 case YANG_CHOICE:
4607 case YANG_CONTAINER:
4608 case YANG_DEVIATION:
4609 case YANG_EXTENSION:
4610 case YANG_FEATURE:
4611 case YANG_GROUPING:
4612 case YANG_IDENTITY:
4613 case YANG_LEAF:
4614 case YANG_LEAF_LIST:
4615 case YANG_LIST:
4616 case YANG_NOTIFICATION:
4617 case YANG_RPC:
4618 case YANG_TYPEDEF:
4619 case YANG_USES:
4620 case YANG_CUSTOM:
4621 mod_stmt = Y_MOD_BODY;
4622 break;
4623 default:
4624 /* error handled in the next switch */
4625 break;
4626 }
4627 prev_kw = kw;
4628
4629 switch (kw) {
4630 /* module header */
4631 case YANG_YANG_VERSION:
4632 ret = parse_yangversion(ctx, data, mod);
4633 break;
4634 case YANG_NAMESPACE:
4635 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->ns, Y_STR_ARG, &mod->exts);
4636 break;
4637 case YANG_PREFIX:
4638 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts);
4639 break;
4640 case YANG_BELONGS_TO:
4641 ret = parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts);
4642 break;
4643
4644 /* linkage */
4645 case YANG_INCLUDE:
4646 ret = parse_include(ctx, data, &mod->includes);
4647 break;
4648 case YANG_IMPORT:
4649 ret = parse_import(ctx, data, &mod->imports);
4650 break;
4651
4652 /* meta */
4653 case YANG_ORGANIZATION:
4654 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->org, Y_STR_ARG, &mod->exts);
4655 break;
4656 case YANG_CONTACT:
4657 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->contact, Y_STR_ARG, &mod->exts);
4658 break;
4659 case YANG_DESCRIPTION:
4660 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->dsc, Y_STR_ARG, &mod->exts);
4661 break;
4662 case YANG_REFERENCE:
4663 ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->ref, Y_STR_ARG, &mod->exts);
4664 break;
4665
4666 /* revision */
4667 case YANG_REVISION:
4668 ret = parse_revision(ctx, data, &mod->revs);
4669 break;
4670
4671 /* body */
4672 case YANG_ANYDATA:
4673 case YANG_ANYXML:
4674 ret = parse_any(ctx, data, kw, &mod->data);
4675 break;
4676 case YANG_CHOICE:
4677 ret = parse_choice(ctx, data, &mod->data);
4678 break;
4679 case YANG_CONTAINER:
4680 ret = parse_container(ctx, data, &mod->data);
4681 break;
4682 case YANG_LEAF:
4683 ret = parse_leaf(ctx, data, &mod->data);
4684 break;
4685 case YANG_LEAF_LIST:
4686 ret = parse_leaflist(ctx, data, &mod->data);
4687 break;
4688 case YANG_LIST:
4689 ret = parse_list(ctx, data, &mod->data);
4690 break;
4691 case YANG_USES:
4692 ret = parse_uses(ctx, data, &mod->data);
4693 break;
4694
4695 case YANG_AUGMENT:
4696 ret = parse_augment(ctx, data, &mod->augments);
4697 break;
4698 case YANG_DEVIATION:
4699 ret = parse_deviation(ctx, data, &mod->deviations);
4700 break;
4701 case YANG_EXTENSION:
4702 ret = parse_extension(ctx, data, &mod->extensions);
4703 break;
4704 case YANG_FEATURE:
4705 ret = parse_feature(ctx, data, &mod->features);
4706 break;
4707 case YANG_GROUPING:
4708 ret = parse_grouping(ctx, data, &mod->groupings);
4709 break;
4710 case YANG_IDENTITY:
4711 ret = parse_identity(ctx, data, &mod->identities);
4712 break;
4713 case YANG_NOTIFICATION:
4714 ret = parse_notif(ctx, data, &mod->notifs);
4715 break;
4716 case YANG_RPC:
4717 ret = parse_action(ctx, data, &mod->rpcs);
4718 break;
4719 case YANG_TYPEDEF:
4720 ret = parse_typedef(ctx, data, &mod->typedefs);
4721 break;
4722 case YANG_CUSTOM:
4723 ret = parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts);
4724 break;
4725
4726 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004727 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004728 return LY_EVALID;
4729 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004730 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004731 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004732 LY_CHECK_RET(ret);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004733
4734 /* mandatory substatements */
4735 if (mod->submodule) {
4736 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004737 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004738 return LY_EVALID;
4739 }
4740 } else {
4741 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004742 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004743 return LY_EVALID;
4744 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004745 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004746 return LY_EVALID;
4747 }
4748 }
4749
4750 return ret;
4751}
4752
Radek Krejcid4557c62018-09-17 11:42:09 +02004753LY_ERR
Michal Vasko7fbc8162018-09-17 10:35:16 +02004754yang_parse(struct ly_ctx *ctx, const char *data, struct lysp_module **mod_p)
4755{
4756 LY_ERR ret = 0;
4757 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004758 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004759 enum yang_keyword kw;
4760 struct lysp_module *mod;
Radek Krejci44ceedc2018-10-02 15:54:31 +02004761 struct ly_parser_ctx context;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004762
Radek Krejci44ceedc2018-10-02 15:54:31 +02004763 context.ctx = ctx;
4764 context.line = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004765
4766 /* "module"/"submodule" */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004767 ret = get_keyword(&context, &data, &kw, &word, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004768 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004769
4770 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004771 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".\n",
Radek Krejcic59bc972018-09-17 16:13:06 +02004772 ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004773 goto error;
4774 }
4775
4776 mod = calloc(1, sizeof *mod);
4777 LY_CHECK_ERR_GOTO(!mod, LOGMEM(ctx), error);
4778 if (kw == YANG_SUBMODULE) {
4779 mod->submodule = 1;
4780 }
4781
4782 /* substatements */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004783 ret = parse_sub_module(&context, &data, mod);
Radek Krejcic59bc972018-09-17 16:13:06 +02004784 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004785
4786 /* read some trailing spaces or new lines */
Radek Krejci44ceedc2018-10-02 15:54:31 +02004787 ret = get_string(&context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
Radek Krejcic59bc972018-09-17 16:13:06 +02004788 LY_CHECK_GOTO(ret, error);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004789
4790 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004791 LOGVAL_YANG(&context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004792 word_len, word);
4793 free(buf);
4794 goto error;
4795 }
4796 assert(!buf);
4797
4798 *mod_p = mod;
4799 return ret;
4800
4801error:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004802 /* TODO free module */
4803 return ret;
4804}