blob: cbac8338dacecfe875e612ef0d017693ac63104f [file] [log] [blame]
Michal Vasko7fbc8162018-09-17 10:35:16 +02001/**
2 * @file parser_yang.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief YANG parser
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <errno.h>
22#include <ctype.h>
23#include <string.h>
24#include <dirent.h>
25#include <assert.h>
26
27#include "common.h"
28#include "context.h"
29#include "libyang.h"
Radek Krejci70853c52018-10-15 14:46:16 +020030#include "tree_schema_internal.h"
Radek Krejci44ceedc2018-10-02 15:54:31 +020031
32/* Macro to check YANG's yang-char grammar rule */
33#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
34 (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
35 (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
36 (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
37 (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
38 (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
39 (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
40 (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
41 (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
42 (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
43
44/* These 2 macros checks YANG's identifier grammar rule */
45#define is_yangidentstartchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
46#define is_yangidentchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || \
47 c == '_' || c == '-' || c == '.')
48
Radek Krejcifaa1eac2018-10-30 14:34:55 +010049#define CHECK_UNIQUENESS(CTX, ARRAY, MEMBER, STMT, IDENT) \
50 if (ARRAY) { \
51 for (unsigned int u = 0; u < LY_ARRAY_SIZE(ARRAY) - 1; ++u) { \
52 if (!strcmp((ARRAY)[u].MEMBER, IDENT)) { \
53 LOGVAL_YANG(CTX, LY_VCODE_DUPIDENT, IDENT, STMT); \
54 return LY_EVALID; \
55 } \
56 } \
57 }
58
Radek Krejci9fcacc12018-10-11 15:59:11 +020059#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
60 if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
61 else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
Radek Krejci44ceedc2018-10-02 15:54:31 +020062
Radek Krejcid5f2b5f2018-10-11 10:54:36 +020063#define MOVE_INPUT(CTX, DATA, COUNT) (*(data))+=COUNT;(CTX)->indent+=COUNT
64
Michal Vaskoea5abea2018-09-18 13:10:54 +020065/**
66 * @brief Loop through all substatements providing, return if there are none.
67 *
Radek Krejci44ceedc2018-10-02 15:54:31 +020068 * @param[in] CTX yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +020069 * @param[in] DATA Raw data to read from.
70 * @param[out] KW YANG keyword read.
71 * @param[out] WORD Pointer to the keyword itself.
72 * @param[out] WORD_LEN Length of the keyword.
73 * @param[out] ERR Variable for error storing.
74 *
75 * @return In case there are no substatements or a fatal error encountered.
76 */
Radek Krejci6d6556c2018-11-08 09:37:45 +010077#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010078 LY_CHECK_RET(get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020079 if (KW == YANG_SEMICOLON) { \
Radek Krejci6d6556c2018-11-08 09:37:45 +010080 CHECKGOTO; \
Radek Krejci6d9b9b52018-11-02 12:43:39 +010081 return LY_SUCCESS; \
Michal Vasko7fbc8162018-09-17 10:35:16 +020082 } \
83 if (KW != YANG_LEFT_BRACE) { \
Radek Krejci44ceedc2018-10-02 15:54:31 +020084 LOGVAL_YANG(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
Michal Vasko7fbc8162018-09-17 10:35:16 +020085 return LY_EVALID; \
86 } \
87 for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
88 !ERR && (KW != YANG_RIGHT_BRACE); \
89 ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
90
Radek Krejci10113652018-11-14 16:56:50 +010091#define YANG_CHECK_STMTVER_RET(CTX, KW, PARENT) \
92 if ((CTX)->mod->version < 2) {LOGVAL_YANG((CTX), LY_VCODE_INCHILDSTMT2, KW, PARENT); return LY_EVALID;}
93
Radek Krejci6d9b9b52018-11-02 12:43:39 +010094static LY_ERR parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
95static LY_ERR parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
96static LY_ERR parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
97static LY_ERR parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
98static LY_ERR parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
99static LY_ERR parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200100
Michal Vaskoea5abea2018-09-18 13:10:54 +0200101/**
102 * @brief Add another character to dynamic buffer, a low-level function.
103 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200104 * Enlarge if needed. Updates \p input as well as \p buf_used.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200105 *
Radek Krejci404251e2018-10-09 12:06:44 +0200106 * @param[in] ctx libyang context for logging.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200107 * @param[in, out] input Input string to process.
108 * @param[in] len Number of bytes to get from the input string and copy into the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200109 * @param[in,out] buf Buffer to use, can be moved by realloc().
110 * @param[in,out] buf_len Current size of the buffer.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200111 * @param[in,out] buf_used Currently used characters of the buffer.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200112 *
113 * @return LY_ERR values.
114 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200115static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200116buf_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 +0200117{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200118 if (*buf_len <= (*buf_used) + len) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200119 *buf_len += 16;
120 *buf = ly_realloc(*buf, *buf_len);
121 LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
122 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200123 memcpy(&(*buf)[*buf_used], *input, len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200124
Radek Krejci44ceedc2018-10-02 15:54:31 +0200125 (*buf_used) += len;
126 (*input) += len;
127
Michal Vasko7fbc8162018-09-17 10:35:16 +0200128 return LY_SUCCESS;
129}
130
Michal Vaskoea5abea2018-09-18 13:10:54 +0200131/**
Radek Krejci44ceedc2018-10-02 15:54:31 +0200132 * @brief Check that \p c is valid UTF8 code point for YANG string.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200133 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200134 * @param[in] ctx yang parser context for logging.
135 * @param[in] c UTF8 code point of a character to check.
136 * @return LY_ERR values.
137 */
138static LY_ERR
139check_stringchar(struct ly_parser_ctx *ctx, unsigned int c)
140{
141 if (!is_yangutf8char(c)) {
142 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, c);
143 return LY_EVALID;
144 }
145 return LY_SUCCESS;
146}
147
148/**
149 * @brief Check that \p c is valid UTF8 code point for YANG identifier.
150 *
151 * @param[in] ctx yang parser context for logging.
152 * @param[in] c UTF8 code point of a character to check.
153 * @param[in] first Flag to check the first character of an identifier, which is more restricted.
Radek Krejcidcc7b322018-10-11 14:24:02 +0200154 * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
155 * 0 - colon not yet found (no prefix)
156 * 1 - \p c is the colon character
157 * 2 - prefix already processed, now processing the identifier
158 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200159 * If the identifier cannot be prefixed, NULL is expected.
160 * @return LY_ERR values.
161 */
162static LY_ERR
163check_identifierchar(struct ly_parser_ctx *ctx, unsigned int c, int first, int *prefix)
164{
165 if (first || (prefix && (*prefix) == 1)) {
166 if (!is_yangidentstartchar(c)) {
167 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
168 return LY_EVALID;
169 }
Radek Krejci9fcacc12018-10-11 15:59:11 +0200170 if (prefix) {
171 if (first) {
172 (*prefix) = 0;
173 } else {
174 (*prefix) = 2;
175 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200176 }
177 } else if (c == ':' && prefix && (*prefix) == 0) {
178 (*prefix) = 1;
179 } else if (!is_yangidentchar(c)) {
180 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
181 return LY_EVALID;
182 }
183
184 return LY_SUCCESS;
185}
186
187/**
188 * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
189 *
190 * @param[in] ctx yang parser context for logging.
191 * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
192 * when function returns.
193 * @param[in] arg Type of the input string to select method of checking character validity.
194 * @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 +0200195 * 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 +0200196 * @param[in,out] word_len Current length of the word pointed to by \p word_p.
197 * @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 +0200198 * @param[in,out] buf_len Current length of \p word_b.
Radek Krejci44ceedc2018-10-02 15:54:31 +0200199 * @param[in] need_buf Flag if the dynamically allocated buffer is required.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200200 *
201 * @return LY_ERR values.
202 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200203static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200204buf_store_char(struct ly_parser_ctx *ctx, const char **input, enum yang_arg arg,
205 char **word_p, size_t *word_len, char **word_b, size_t *buf_len, int need_buf)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200206{
Radek Krejci404251e2018-10-09 12:06:44 +0200207 int prefix = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200208 unsigned int c;
209 size_t len;
210
211 /* get UTF8 code point (and number of bytes coding the character) */
212 LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
213 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
214 (*input) -= len;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200215 if (c == '\n') {
216 ctx->indent = 0;
217 } else {
218 /* note - even the multibyte character is count as 1 */
219 ++ctx->indent;
220 }
221
Radek Krejci44ceedc2018-10-02 15:54:31 +0200222 /* check character validity */
223 switch (arg) {
224 case Y_IDENTIF_ARG:
225 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
226 break;
227 case Y_PREF_IDENTIF_ARG:
228 LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
229 break;
230 case Y_STR_ARG:
231 case Y_MAYBE_STR_ARG:
232 LY_CHECK_RET(check_stringchar(ctx, c));
233 break;
234 }
235
Michal Vasko7fbc8162018-09-17 10:35:16 +0200236 if (word_b && *word_b) {
237 /* add another character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200238 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200239 return LY_EMEM;
240 }
241
242 /* in case of realloc */
243 *word_p = *word_b;
244 } else if (need_buf) {
245 /* first time we need a buffer, copy everything read up to now */
246 if (*word_len) {
247 *word_b = malloc(*word_len);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200248 LY_CHECK_ERR_RET(!*word_b, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200249 *buf_len = *word_len;
250 memcpy(*word_b, *word_p, *word_len);
251 }
252
253 /* add this new character into buffer */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200254 if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200255 return LY_EMEM;
256 }
257
258 /* in case of realloc */
259 *word_p = *word_b;
260 } else {
261 /* just remember the first character pointer */
262 if (!*word_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200263 *word_p = (char *)(*input);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200264 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200265 /* ... and update the word's length */
266 (*word_len) += len;
267 (*input) += len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200268 }
269
270 return LY_SUCCESS;
271}
272
Michal Vaskoea5abea2018-09-18 13:10:54 +0200273/**
274 * @brief Skip YANG comment in data.
275 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200276 * @param[in] ctx yang parser context for logging.
277 * @param[in,out] data Data to read from, automatically moved after the comment.
278 * @param[in] comment Type of the comment to process:
279 * 1 for a one-line comment,
280 * 2 for a block comment.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200281 *
282 * @return LY_ERR values.
283 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200284static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200285skip_comment(struct ly_parser_ctx *ctx, const char **data, int comment)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200286{
Radek Krejci80dd33e2018-09-26 15:57:18 +0200287 /* internal statuses: 0 - comment ended,
288 * 1 - in line comment,
289 * 2 - in block comment,
290 * 3 - in block comment with last read character '*'
291 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200292 while (**data && comment) {
293 switch (comment) {
294 case 1:
295 if (**data == '\n') {
296 comment = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200297 ++ctx->line;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200298 }
299 break;
300 case 2:
301 if (**data == '*') {
Radek Krejci15c80ca2018-10-09 11:01:31 +0200302 comment = 3;
303 } else if (**data == '\n') {
304 ++ctx->line;
305 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200306 break;
307 case 3:
308 if (**data == '/') {
309 comment = 0;
310 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200311 if (**data == '\n') {
312 ++ctx->line;
313 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200314 comment = 2;
315 }
316 break;
317 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200318 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200319 }
320
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200321 if (**data == '\n') {
322 ctx->indent = 0;
323 } else {
324 ++ctx->indent;
325 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200326 ++(*data);
327 }
328
329 if (!**data && (comment > 1)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200330 LOGVAL_YANG(ctx, LYVE_SYNTAX, "Unexpected end-of-file, non-terminated comment.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200331 return LY_EVALID;
332 }
333
334 return LY_SUCCESS;
335}
336
Michal Vaskoea5abea2018-09-18 13:10:54 +0200337/**
338 * @brief Read a quoted string from data.
339 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200340 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200341 * @param[in,out] data Data to read from, always moved to currently handled character.
342 * @param[in] arg Type of YANG keyword argument expected.
343 * @param[out] word_p Pointer to the read quoted string.
344 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
345 * set to NULL. Otherwise equal to \p word_p.
346 * @param[out] word_len Length of the read quoted string.
347 * @param[out] buf_len Length of the dynamically-allocated buffer \p word_b.
348 * @param[in] indent Current indent (number of YANG spaces). Needed for correct multi-line string
349 * indenation in the final quoted string.
350 *
351 * @return LY_ERR values.
352 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200353static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200354read_qstring(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len,
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200355 size_t *buf_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200356{
357 /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
358 * 4 - string finished, now skipping whitespaces looking for +,
359 * 5 - string continues after +, skipping whitespaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200360 unsigned int string, block_indent = 0, current_indent = 0, need_buf = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200361 const char *c;
362
363 if (**data == '\"') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200364 string = 2;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200365 current_indent = block_indent = ctx->indent + 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200366 } else {
367 assert(**data == '\'');
368 string = 1;
369 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200370 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200371
372 while (**data && string) {
373 switch (string) {
374 case 1:
375 switch (**data) {
376 case '\'':
377 /* string may be finished, but check for + */
378 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200379 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200380 break;
381 default:
382 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200383 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 +0200384 break;
385 }
386 break;
387 case 2:
388 switch (**data) {
389 case '\"':
390 /* string may be finished, but check for + */
391 string = 4;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200392 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200393 break;
394 case '\\':
395 /* special character following */
396 string = 3;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200397 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200398 break;
399 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200400 if (current_indent < block_indent) {
401 ++current_indent;
402 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200403 } else {
404 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200405 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 +0200406 }
407 break;
408 case '\t':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200409 if (current_indent < block_indent) {
410 assert(need_buf);
411 current_indent += 8;
412 ctx->indent += 8;
413 for (; current_indent > block_indent; --current_indent, --ctx->indent) {
414 /* store leftover spaces from the tab */
415 c = " ";
416 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 +0200417 }
Radek Krejci44ceedc2018-10-02 15:54:31 +0200418 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200419 } else {
420 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200421 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200422 /* additional characters for indentation - only 1 was count in buf_store_char */
423 ctx->indent += 7;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200424 }
425 break;
426 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200427 if (block_indent) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200428 /* we will be removing the indents so we need our own buffer */
429 need_buf = 1;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200430
431 /* remove trailing tabs and spaces */
432 while ((*word_len) && ((*word_p)[(*word_len) - 1] == '\t' || (*word_p)[(*word_len) - 1] == ' ')) {
433 --(*word_len);
434 }
435
436 /* start indentation */
437 current_indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200438 }
439
440 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200441 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf));
442
443 /* maintain line number */
444 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200445
446 /* reset context indentation counter for possible string after this one */
447 ctx->indent = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200448 break;
449 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200450 /* first non-whitespace character, stop eating indentation */
451 current_indent = block_indent;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200452
453 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200454 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 +0200455 break;
456 }
457 break;
458 case 3:
459 /* string encoded characters */
460 switch (**data) {
461 case 'n':
462 c = "\n";
463 break;
464 case 't':
465 c = "\t";
466 break;
467 case '\"':
468 c = *data;
469 break;
470 case '\\':
471 c = *data;
472 break;
473 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200474 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200475 return LY_EVALID;
476 }
477
478 /* check and store character */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200479 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 +0200480
481 string = 2;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200482 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200483 break;
484 case 4:
485 switch (**data) {
486 case '+':
487 /* string continues */
488 string = 5;
Radek Krejciefd22f62018-09-27 11:47:58 +0200489 need_buf = 1;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200490 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200491 case '\n':
492 ++ctx->line;
493 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200494 case ' ':
495 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200496 /* just skip */
497 break;
498 default:
499 /* string is finished */
500 goto string_end;
501 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200502 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200503 break;
504 case 5:
505 switch (**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200506 case '\n':
507 ++ctx->line;
508 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200509 case ' ':
510 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200511 /* skip */
512 break;
513 case '\'':
514 string = 1;
515 break;
516 case '\"':
517 string = 2;
518 break;
519 default:
520 /* it must be quoted again */
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200521 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200522 return LY_EVALID;
523 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200524 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200525 break;
526 default:
527 return LY_EINT;
528 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200529 }
530
531string_end:
532 return LY_SUCCESS;
533}
534
Michal Vaskoea5abea2018-09-18 13:10:54 +0200535/**
536 * @brief Get another YANG string from the raw data.
537 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200538 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200539 * @param[in,out] data Data to read from, always moved to currently handled character.
540 * @param[in] arg Type of YANG keyword argument expected.
Michal Vasko2ca70f52018-09-27 11:04:51 +0200541 * @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 +0200542 * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read string. If not needed,
543 * set to NULL. Otherwise equal to \p word_p.
544 * @param[out] word_len Length of the read string.
545 *
546 * @return LY_ERR values.
Michal Vasko7fbc8162018-09-17 10:35:16 +0200547 */
548static LY_ERR
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200549get_argument(struct ly_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b, size_t *word_len)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200550{
Radek Krejci44ceedc2018-10-02 15:54:31 +0200551 size_t buf_len = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200552
553 /* word buffer - dynamically allocated */
554 *word_b = NULL;
555
556 /* word pointer - just a pointer to data */
557 *word_p = NULL;
558
559 *word_len = 0;
560 while (**data) {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200561 switch (**data) {
562 case '\'':
563 case '\"':
564 if (*word_len) {
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200565 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
566 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
567 "unquoted string character, optsep, semicolon or opening brace");
568 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200569 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100570 LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200571 goto str_end;
572 case '/':
Radek Krejci44ceedc2018-10-02 15:54:31 +0200573 if ((*data)[1] == '/') {
574 /* one-line comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200575 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100576 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200577 } else if ((*data)[1] == '*') {
578 /* block comment */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200579 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100580 LY_CHECK_RET(skip_comment(ctx, data, 2));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200581 } else {
582 /* not a comment after all */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100583 LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0));
Radek Krejci44ceedc2018-10-02 15:54:31 +0200584 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200585 break;
586 case ' ':
587 if (*word_len) {
588 /* word is finished */
589 goto str_end;
590 }
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200591 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200592 break;
593 case '\t':
594 if (*word_len) {
595 /* word is finished */
596 goto str_end;
597 }
598 /* tabs count for 8 spaces */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200599 ctx->indent += 8;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200600
601 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200602 break;
603 case '\n':
604 if (*word_len) {
605 /* word is finished */
606 goto str_end;
607 }
608 /* reset indent */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200609 ctx->indent = 0;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200610
611 /* track line numbers */
612 ++ctx->line;
613
614 ++(*data);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200615 break;
616 case ';':
617 case '{':
618 if (*word_len || (arg == Y_MAYBE_STR_ARG)) {
619 /* word is finished */
620 goto str_end;
621 }
622
Radek Krejci44ceedc2018-10-02 15:54:31 +0200623 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200624 return LY_EVALID;
Radek Krejcifc62d7e2018-10-11 12:56:42 +0200625 case '}':
626 /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
627 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, 1, *data,
628 "unquoted string character, optsep, semicolon or opening brace");
629 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200630 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200631 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 +0200632 break;
633 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200634 }
635
636str_end:
Radek Krejci44ceedc2018-10-02 15:54:31 +0200637 /* terminating NULL byte for buf */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200638 if (*word_b) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200639 (*word_b) = ly_realloc(*word_b, (*word_len) + 1);
640 LY_CHECK_ERR_RET(!(*word_b), LOGMEM(ctx->ctx), LY_EMEM);
641 (*word_b)[*word_len] = '\0';
Michal Vasko7fbc8162018-09-17 10:35:16 +0200642 *word_p = *word_b;
643 }
644
645 return LY_SUCCESS;
646}
647
Michal Vaskoea5abea2018-09-18 13:10:54 +0200648/**
649 * @brief Get another YANG keyword from the raw data.
650 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200651 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200652 * @param[in,out] data Data to read from, always moved to currently handled character.
653 * @param[out] kw YANG keyword read.
654 * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
655 * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
656 *
657 * @return LY_ERR values.
658 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200659static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200660get_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 +0200661{
Michal Vasko7fbc8162018-09-17 10:35:16 +0200662 int prefix;
663 const char *word_start;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200664 unsigned int c;
665 size_t len;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200666
667 if (word_p) {
668 *word_p = NULL;
669 *word_len = 0;
670 }
671
672 /* first skip "optsep", comments */
673 while (**data) {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200674 switch (**data) {
675 case '/':
676 if ((*data)[1] == '/') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200677 /* one-line comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200678 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100679 LY_CHECK_RET(skip_comment(ctx, data, 1));
Radek Krejcidcc7b322018-10-11 14:24:02 +0200680 } else if ((*data)[1] == '*') {
Michal Vasko7fbc8162018-09-17 10:35:16 +0200681 /* block comment */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200682 MOVE_INPUT(ctx, data, 2);
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100683 LY_CHECK_RET(skip_comment(ctx, data, 2));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200684 } else {
Radek Krejcidcc7b322018-10-11 14:24:02 +0200685 /* error - not a comment after all, keyword cannot start with slash */
686 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
687 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200688 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200689 break;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200690 case '\n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200691 /* skip whitespaces (optsep) */
Radek Krejci44ceedc2018-10-02 15:54:31 +0200692 ++ctx->line;
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200693 ctx->indent = 0;
694 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200695 case ' ':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200696 /* skip whitespaces (optsep) */
697 ++ctx->indent;
698 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200699 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200700 /* skip whitespaces (optsep) */
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200701 ctx->indent += 8;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200702 break;
703 default:
704 /* either a keyword start or an invalid character */
705 goto keyword_start;
706 }
707
708 ++(*data);
709 }
710
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200711#define IF_KW(STR, LEN, STMT) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);*kw=STMT;}
712#define IF_KW_PREFIX(STR, LEN) if (!strncmp(*(data), STR, LEN)) {MOVE_INPUT(ctx, data, LEN);
713#define IF_KW_PREFIX_END }
714
Michal Vasko7fbc8162018-09-17 10:35:16 +0200715keyword_start:
716 word_start = *data;
717 *kw = YANG_NONE;
718
719 /* read the keyword itself */
720 switch (**data) {
721 case 'a':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200722 MOVE_INPUT(ctx, data, 1);
723 IF_KW("rgument", 7, YANG_ARGUMENT)
724 else IF_KW("ugment", 6, YANG_AUGMENT)
725 else IF_KW("ction", 5, YANG_ACTION)
726 else IF_KW_PREFIX("ny", 2)
727 IF_KW("data", 4, YANG_ANYDATA)
728 else IF_KW("xml", 3, YANG_ANYXML)
729 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200730 break;
731 case 'b':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200732 MOVE_INPUT(ctx, data, 1);
733 IF_KW("ase", 3, YANG_BASE)
734 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
735 else IF_KW("it", 2, YANG_BIT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200736 break;
737 case 'c':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200738 MOVE_INPUT(ctx, data, 1);
739 IF_KW("ase", 3, YANG_CASE)
740 else IF_KW("hoice", 5, YANG_CHOICE)
741 else IF_KW_PREFIX("on", 2)
742 IF_KW("fig", 3, YANG_CONFIG)
743 else IF_KW_PREFIX("ta", 2)
744 IF_KW("ct", 2, YANG_CONTACT)
745 else IF_KW("iner", 4, YANG_CONTAINER)
746 IF_KW_PREFIX_END
747 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200748 break;
749 case 'd':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200750 MOVE_INPUT(ctx, data, 1);
751 IF_KW_PREFIX("e", 1)
752 IF_KW("fault", 5, YANG_DEFAULT)
753 else IF_KW("scription", 9, YANG_DESCRIPTION)
754 else IF_KW_PREFIX("viat", 4)
755 IF_KW("e", 1, YANG_DEVIATE)
756 else IF_KW("ion", 3, YANG_DEVIATION)
757 IF_KW_PREFIX_END
758 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200759 break;
760 case 'e':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200761 MOVE_INPUT(ctx, data, 1);
762 IF_KW("num", 3, YANG_ENUM)
763 else IF_KW_PREFIX("rror-", 5)
764 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
765 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
766 IF_KW_PREFIX_END
767 else IF_KW("xtension", 8, YANG_EXTENSION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200768 break;
769 case 'f':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200770 MOVE_INPUT(ctx, data, 1);
771 IF_KW("eature", 6, YANG_FEATURE)
772 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200773 break;
774 case 'g':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200775 MOVE_INPUT(ctx, data, 1);
776 IF_KW("rouping", 7, YANG_GROUPING)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200777 break;
778 case 'i':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200779 MOVE_INPUT(ctx, data, 1);
780 IF_KW("dentity", 7, YANG_IDENTITY)
781 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
782 else IF_KW("mport", 5, YANG_IMPORT)
783 else IF_KW_PREFIX("n", 1)
784 IF_KW("clude", 5, YANG_INCLUDE)
785 else IF_KW("put", 3, YANG_INPUT)
786 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200787 break;
788 case 'k':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200789 MOVE_INPUT(ctx, data, 1);
790 IF_KW("ey", 2, YANG_KEY)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200791 break;
792 case 'l':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200793 MOVE_INPUT(ctx, data, 1);
794 IF_KW_PREFIX("e", 1)
795 IF_KW("af-list", 7, YANG_LEAF_LIST)
796 else IF_KW("af", 2, YANG_LEAF)
797 else IF_KW("ngth", 4, YANG_LENGTH)
798 IF_KW_PREFIX_END
799 else IF_KW("ist", 3, YANG_LIST)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200800 break;
801 case 'm':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200802 MOVE_INPUT(ctx, data, 1);
803 IF_KW_PREFIX("a", 1)
804 IF_KW("ndatory", 7, YANG_MANDATORY)
805 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
806 IF_KW_PREFIX_END
807 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
808 else IF_KW("ust", 3, YANG_MUST)
809 else IF_KW_PREFIX("od", 2)
810 IF_KW("ule", 3, YANG_MODULE)
811 else IF_KW("ifier", 5, YANG_MODIFIER)
812 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200813 break;
814 case 'n':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200815 MOVE_INPUT(ctx, data, 1);
816 IF_KW("amespace", 8, YANG_NAMESPACE)
817 else IF_KW("otification", 11, YANG_NOTIFICATION)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200818 break;
819 case 'o':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200820 MOVE_INPUT(ctx, data, 1);
821 IF_KW_PREFIX("r", 1)
822 IF_KW("dered-by", 8, YANG_ORDERED_BY)
823 else IF_KW("ganization", 10, YANG_ORGANIZATION)
824 IF_KW_PREFIX_END
825 else IF_KW("utput", 5, YANG_OUTPUT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200826 break;
827 case 'p':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200828 MOVE_INPUT(ctx, data, 1);
829 IF_KW("ath", 3, YANG_PATH)
830 else IF_KW("attern", 6, YANG_PATTERN)
831 else IF_KW("osition", 7, YANG_POSITION)
832 else IF_KW_PREFIX("re", 2)
833 IF_KW("fix", 3, YANG_PREFIX)
834 else IF_KW("sence", 5, YANG_PRESENCE)
835 IF_KW_PREFIX_END
Michal Vasko7fbc8162018-09-17 10:35:16 +0200836 break;
837 case 'r':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200838 MOVE_INPUT(ctx, data, 1);
839 IF_KW("ange", 4, YANG_RANGE)
840 else IF_KW_PREFIX("e", 1)
841 IF_KW_PREFIX("f", 1)
842 IF_KW("erence", 6, YANG_REFERENCE)
843 else IF_KW("ine", 3, YANG_REFINE)
844 IF_KW_PREFIX_END
845 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
846 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
847 else IF_KW("vision", 6, YANG_REVISION)
848 IF_KW_PREFIX_END
849 else IF_KW("pc", 2, YANG_RPC)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200850 break;
851 case 's':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200852 MOVE_INPUT(ctx, data, 1);
853 IF_KW("tatus", 5, YANG_STATUS)
854 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200855 break;
856 case 't':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200857 MOVE_INPUT(ctx, data, 1);
858 IF_KW("ypedef", 6, YANG_TYPEDEF)
859 else IF_KW("ype", 3, YANG_TYPE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200860 break;
861 case 'u':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200862 MOVE_INPUT(ctx, data, 1);
863 IF_KW_PREFIX("ni", 2)
864 IF_KW("que", 3, YANG_UNIQUE)
865 else IF_KW("ts", 2, YANG_UNITS)
866 IF_KW_PREFIX_END
867 else IF_KW("ses", 3, YANG_USES)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200868 break;
869 case 'v':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200870 MOVE_INPUT(ctx, data, 1);
871 IF_KW("alue", 4, YANG_VALUE)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200872 break;
873 case 'w':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200874 MOVE_INPUT(ctx, data, 1);
875 IF_KW("hen", 3, YANG_WHEN)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200876 break;
877 case 'y':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200878 MOVE_INPUT(ctx, data, 1);
879 IF_KW("ang-version", 11, YANG_YANG_VERSION)
880 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
Michal Vasko7fbc8162018-09-17 10:35:16 +0200881 break;
882 case ';':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200883 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200884 *kw = YANG_SEMICOLON;
Radek Krejci626df482018-10-11 15:06:31 +0200885 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200886 case '{':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200887 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200888 *kw = YANG_LEFT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200889 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200890 case '}':
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200891 MOVE_INPUT(ctx, data, 1);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200892 *kw = YANG_RIGHT_BRACE;
Radek Krejci626df482018-10-11 15:06:31 +0200893 goto success;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200894 default:
895 break;
896 }
897
898 if (*kw != YANG_NONE) {
899 /* make sure we have the whole keyword */
900 switch (**data) {
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200901 case '\n':
902 ++ctx->line;
903 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200904 case ' ':
905 case '\t':
Michal Vasko7fbc8162018-09-17 10:35:16 +0200906 /* mandatory "sep" */
907 break;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200908 case ':':
909 /* keyword is not actually a keyword, but prefix of an extension.
910 * To avoid repeated check of the prefix syntax, move to the point where the colon was read
911 * and we will be checking the keyword (extension instance) itself */
912 prefix = 1;
913 MOVE_INPUT(ctx, data, 1);
914 goto extension;
Radek Krejcidcc7b322018-10-11 14:24:02 +0200915 case '{':
916 /* allowed only for input and output statements which can be without arguments */
917 if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
918 break;
919 }
920 /* fallthrough */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200921 default:
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200922 MOVE_INPUT(ctx, data, 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +0200923 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
924 "a keyword followed by a separator");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200925 return LY_EVALID;
926 }
927 } else {
928 /* still can be an extension */
929 prefix = 0;
Radek Krejci156ccaf2018-10-15 15:49:17 +0200930extension:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200931 while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200932 LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
933 LOGVAL_YANG(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200934 ++ctx->indent;
Radek Krejci44ceedc2018-10-02 15:54:31 +0200935 /* check character validity */
936 LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200937 }
938 if (!**data) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200939 LOGVAL_YANG(ctx, LY_VCODE_EOF);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200940 return LY_EVALID;
941 }
942
943 /* prefix is mandatory for extension instances */
Radek Krejcidcc7b322018-10-11 14:24:02 +0200944 if (prefix != 2) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200945 LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
Michal Vasko7fbc8162018-09-17 10:35:16 +0200946 return LY_EVALID;
947 }
948
949 *kw = YANG_CUSTOM;
950 }
Radek Krejci626df482018-10-11 15:06:31 +0200951success:
Michal Vasko7fbc8162018-09-17 10:35:16 +0200952 if (word_p) {
953 *word_p = (char *)word_start;
954 *word_len = *data - word_start;
955 }
956
957 return LY_SUCCESS;
958}
959
Michal Vaskoea5abea2018-09-18 13:10:54 +0200960/**
961 * @brief Parse extension instance substatements.
962 *
Radek Krejci44ceedc2018-10-02 15:54:31 +0200963 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +0200964 * @param[in,out] data Data to read from, always moved to currently handled character.
965 * @param[in] word Extension instance substatement name (keyword).
966 * @param[in] word_len Extension instance substatement name length.
967 * @param[in,out] child Children of this extension instance to add to.
968 *
969 * @return LY_ERR values.
970 */
Michal Vasko7fbc8162018-09-17 10:35:16 +0200971static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +0200972parse_ext_substmt(struct ly_parser_ctx *ctx, const char **data, char *word, size_t word_len,
Michal Vasko7fbc8162018-09-17 10:35:16 +0200973 struct lysp_stmt **child)
974{
975 char *buf;
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100976 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +0200977 enum yang_keyword kw;
978 struct lysp_stmt *stmt, *par_child;
979
980 stmt = calloc(1, sizeof *stmt);
981 LY_CHECK_ERR_RET(!stmt, LOGMEM(NULL), LY_EMEM);
982
Radek Krejci44ceedc2018-10-02 15:54:31 +0200983 stmt->stmt = lydict_insert(ctx->ctx, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +0200984
985 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100986 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +0200987
Radek Krejci0ae092d2018-09-20 16:43:19 +0200988 if (word) {
989 if (buf) {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200990 stmt->arg = lydict_insert_zc(ctx->ctx, word);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200991 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +0200992 stmt->arg = lydict_insert(ctx->ctx, word, word_len);
Radek Krejci0ae092d2018-09-20 16:43:19 +0200993 }
Michal Vasko7fbc8162018-09-17 10:35:16 +0200994 }
995
996 /* insert into parent statements */
997 if (!*child) {
998 *child = stmt;
999 } else {
1000 for (par_child = *child; par_child->next; par_child = par_child->next);
1001 par_child->next = stmt;
1002 }
1003
Radek Krejci6d6556c2018-11-08 09:37:45 +01001004 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, ) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001005 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &stmt->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001006 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001007 return ret;
1008}
1009
Michal Vaskoea5abea2018-09-18 13:10:54 +02001010/**
1011 * @brief Parse extension instance.
1012 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001013 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001014 * @param[in,out] data Data to read from, always moved to currently handled character.
1015 * @param[in] ext_name Extension instance substatement name (keyword).
1016 * @param[in] ext_name_len Extension instance substatement name length.
1017 * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
1018 * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
1019 * @param[in,out] exts Extension instances to add to.
1020 *
1021 * @return LY_ERR values.
1022 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001023static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001024parse_ext(struct ly_parser_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001025 uint32_t insubstmt_index, struct lysp_ext_instance **exts)
1026{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001027 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001028 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001029 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001030 struct lysp_ext_instance *e;
1031 enum yang_keyword kw;
1032
Radek Krejci2c4e7172018-10-19 15:56:26 +02001033 LY_ARRAY_NEW_RET(ctx->ctx, *exts, e, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001034
1035 /* store name and insubstmt info */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001036 e->name = lydict_insert(ctx->ctx, ext_name, ext_name_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001037 e->insubstmt = insubstmt;
1038 e->insubstmt_index = insubstmt_index;
1039
1040 /* get optional argument */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001041 LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001042
Radek Krejci0ae092d2018-09-20 16:43:19 +02001043 if (word) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001044 INSERT_WORD(ctx, buf, e->argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001045 }
1046
Radek Krejci6d6556c2018-11-08 09:37:45 +01001047 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001048 LY_CHECK_RET(parse_ext_substmt(ctx, data, word, word_len, &e->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001049 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001050 return ret;
1051}
1052
Michal Vaskoea5abea2018-09-18 13:10:54 +02001053/**
1054 * @brief Parse a generic text field without specific constraints. Those are contact, organization,
1055 * description, etc...
1056 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001057 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001058 * @param[in,out] data Data to read from, always moved to currently handled character.
1059 * @param[in] substmt Type of this substatement.
1060 * @param[in] substmt_index Index of this substatement.
1061 * @param[in,out] value Place to store the parsed value.
1062 * @param[in] arg Type of the YANG keyword argument (of the value).
1063 * @param[in,out] exts Extension instances to add to.
1064 *
1065 * @return LY_ERR values.
1066 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001067static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001068parse_text_field(struct ly_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
Michal Vasko7fbc8162018-09-17 10:35:16 +02001069 const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
1070{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001071 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001072 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001073 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001074 enum yang_keyword kw;
1075
1076 if (*value) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001077 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001078 return LY_EVALID;
1079 }
1080
1081 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001082 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001083
1084 /* store value and spend buf if allocated */
Radek Krejci44ceedc2018-10-02 15:54:31 +02001085 INSERT_WORD(ctx, buf, *value, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001086
Radek Krejci6d6556c2018-11-08 09:37:45 +01001087 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001088 switch (kw) {
1089 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001090 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001091 break;
1092 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001093 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001094 return LY_EVALID;
1095 }
1096 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001097 return ret;
1098}
1099
Michal Vaskoea5abea2018-09-18 13:10:54 +02001100/**
1101 * @brief Parse the yang-version statement.
1102 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001103 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001104 * @param[in,out] data Data to read from, always moved to currently handled character.
1105 * @param[in] mod Module to store the parsed information in.
1106 *
1107 * @return LY_ERR values.
1108 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001109static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001110parse_yangversion(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001111{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001112 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001113 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001114 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001115 enum yang_keyword kw;
1116
1117 if (mod->version) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001118 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001119 return LY_EVALID;
1120 }
1121
1122 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001123 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001124
1125 if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
1126 mod->version = LYS_VERSION_1_0;
1127 } else if ((word_len == 3) && !strncmp(word, "1.1", word_len)) {
1128 mod->version = LYS_VERSION_1_1;
1129 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001130 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001131 free(buf);
1132 return LY_EVALID;
1133 }
1134 free(buf);
1135
Radek Krejci6d6556c2018-11-08 09:37:45 +01001136 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001137 switch (kw) {
1138 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001139 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001140 break;
1141 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001142 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001143 return LY_EVALID;
1144 }
1145 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001146 return ret;
1147}
1148
Michal Vaskoea5abea2018-09-18 13:10:54 +02001149/**
1150 * @brief Parse the belongs-to statement.
1151 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001152 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001153 * @param[in,out] data Data to read from, always moved to currently handled character.
1154 * @param[in,out] belongsto Place to store the parsed value.
1155 * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
1156 * @param[in,out] exts Extension instances to add to.
1157 *
1158 * @return LY_ERR values.
1159 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001160static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001161parse_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 +02001162{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001163 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001164 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001165 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001166 enum yang_keyword kw;
1167
1168 if (*belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001169 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001170 return LY_EVALID;
1171 }
1172
1173 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001174 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001175
Radek Krejci44ceedc2018-10-02 15:54:31 +02001176 INSERT_WORD(ctx, buf, *belongsto, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001177 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001178 switch (kw) {
1179 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001180 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001181 break;
1182 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001183 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001184 break;
1185 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001186 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001187 return LY_EVALID;
1188 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001189 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001190 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001191checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001192 /* mandatory substatements */
1193 if (!*prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001194 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "belongs-to");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001195 return LY_EVALID;
1196 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001197 return ret;
1198}
1199
Michal Vaskoea5abea2018-09-18 13:10:54 +02001200/**
1201 * @brief Parse the revision-date statement.
1202 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001203 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001204 * @param[in,out] data Data to read from, always moved to currently handled character.
1205 * @param[in,out] rev Array to store the parsed value in.
1206 * @param[in,out] exts Extension instances to add to.
1207 *
1208 * @return LY_ERR values.
1209 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001210static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001211parse_revisiondate(struct ly_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001212{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001213 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001214 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001215 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001216 enum yang_keyword kw;
1217
1218 if (rev[0]) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001219 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001220 return LY_EVALID;
1221 }
1222
1223 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001224 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001225
1226 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001227 if (lysp_check_date(ctx, word, word_len, "revision-date")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001228 free(buf);
1229 return LY_EVALID;
1230 }
1231
1232 /* store value and spend buf if allocated */
1233 strncpy(rev, word, word_len);
1234 free(buf);
1235
Radek Krejci6d6556c2018-11-08 09:37:45 +01001236 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001237 switch (kw) {
1238 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001239 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001240 break;
1241 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001242 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001243 return LY_EVALID;
1244 }
1245 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001246 return ret;
1247}
1248
Michal Vaskoea5abea2018-09-18 13:10:54 +02001249/**
1250 * @brief Parse the include statement.
1251 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001252 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001253 * @param[in,out] data Data to read from, always moved to currently handled character.
1254 * @param[in,out] includes Parsed includes to add to.
1255 *
1256 * @return LY_ERR values.
1257 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001258static LY_ERR
Radek Krejcid33273d2018-10-25 14:55:52 +02001259parse_include(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001260{
Radek Krejcid33273d2018-10-25 14:55:52 +02001261 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001262 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001263 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001264 enum yang_keyword kw;
1265 struct lysp_include *inc;
1266
Radek Krejcid33273d2018-10-25 14:55:52 +02001267 LY_ARRAY_NEW_RET(ctx->ctx, mod->includes, inc, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001268
1269 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001270 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001271
Radek Krejci086c7132018-10-26 15:29:04 +02001272 INSERT_WORD(ctx, buf, inc->name, word, word_len);
1273
Radek Krejcifaa1eac2018-10-30 14:34:55 +01001274 /* submodules share the namespace with the module names, so there must not be
1275 * a module of the same name in the context, no need for revision matching */
1276 if (!strcmp(ctx->mod->name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
1277 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
1278 return LY_EVALID;
1279 }
1280
Radek Krejci6d6556c2018-11-08 09:37:45 +01001281 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001282 switch (kw) {
1283 case YANG_DESCRIPTION:
Radek Krejci10113652018-11-14 16:56:50 +01001284 YANG_CHECK_STMTVER_RET(ctx, "description", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001285 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001286 break;
1287 case YANG_REFERENCE:
Radek Krejci10113652018-11-14 16:56:50 +01001288 YANG_CHECK_STMTVER_RET(ctx, "reference", "include");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001289 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001290 break;
1291 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001292 LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001293 break;
1294 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001295 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001296 break;
1297 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001298 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001299 return LY_EVALID;
1300 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001301 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001302 return ret;
1303}
1304
Michal Vaskoea5abea2018-09-18 13:10:54 +02001305/**
1306 * @brief Parse the import statement.
1307 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001308 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001309 * @param[in,out] data Data to read from, always moved to currently handled character.
1310 * @param[in,out] imports Parsed imports to add to.
1311 *
1312 * @return LY_ERR values.
1313 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001314static LY_ERR
Radek Krejci70853c52018-10-15 14:46:16 +02001315parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *module)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001316{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001317 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001318 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001319 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001320 enum yang_keyword kw;
1321 struct lysp_import *imp;
1322
Radek Krejci2c4e7172018-10-19 15:56:26 +02001323 LY_ARRAY_NEW_RET(ctx->ctx, module->imports, imp, LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001324
1325 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001326 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001327 INSERT_WORD(ctx, buf, imp->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001328
Radek Krejci6d6556c2018-11-08 09:37:45 +01001329 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001330 switch (kw) {
1331 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001332 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
Radek Krejci70853c52018-10-15 14:46:16 +02001333 LY_CHECK_RET(lysp_check_prefix(ctx, module, &imp->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001334 break;
1335 case YANG_DESCRIPTION:
Radek Krejci10113652018-11-14 16:56:50 +01001336 YANG_CHECK_STMTVER_RET(ctx, "description", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001337 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001338 break;
1339 case YANG_REFERENCE:
Radek Krejci10113652018-11-14 16:56:50 +01001340 YANG_CHECK_STMTVER_RET(ctx, "reference", "import");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001341 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001342 break;
1343 case YANG_REVISION_DATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001344 LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001345 break;
1346 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001347 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001348 break;
1349 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001350 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001351 return LY_EVALID;
1352 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001353 }
Radek Krejcic59bc972018-09-17 16:13:06 +02001354 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001355checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02001356 /* mandatory substatements */
Radek Krejci086c7132018-10-26 15:29:04 +02001357 LY_CHECK_ERR_RET(!imp->prefix, LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "import"), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001358
1359 return ret;
1360}
1361
Michal Vaskoea5abea2018-09-18 13:10:54 +02001362/**
1363 * @brief Parse the revision statement.
1364 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001365 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001366 * @param[in,out] data Data to read from, always moved to currently handled character.
1367 * @param[in,out] revs Parsed revisions to add to.
1368 *
1369 * @return LY_ERR values.
1370 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001371static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001372parse_revision(struct ly_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001373{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001374 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001375 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001376 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001377 enum yang_keyword kw;
1378 struct lysp_revision *rev;
1379
Radek Krejci2c4e7172018-10-19 15:56:26 +02001380 LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001381
1382 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001383 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001384
1385 /* check value */
Radek Krejcibbe09a92018-11-08 09:36:54 +01001386 if (lysp_check_date(ctx, word, word_len, "revision")) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001387 return LY_EVALID;
1388 }
1389
Radek Krejcib7db73a2018-10-24 14:18:40 +02001390 strncpy(rev->date, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001391 free(buf);
1392
Radek Krejci6d6556c2018-11-08 09:37:45 +01001393 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001394 switch (kw) {
1395 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001396 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001397 break;
1398 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001399 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001400 break;
1401 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001402 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001403 break;
1404 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001405 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001406 return LY_EVALID;
1407 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001408 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001409 return ret;
1410}
1411
Michal Vaskoea5abea2018-09-18 13:10:54 +02001412/**
1413 * @brief Parse a generic text field that can have more instances such as base.
1414 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001415 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001416 * @param[in,out] data Data to read from, always moved to currently handled character.
1417 * @param[in] substmt Type of this substatement.
1418 * @param[in,out] texts Parsed values to add to.
1419 * @param[in] arg Type of the expected argument.
1420 * @param[in,out] exts Extension instances to add to.
1421 *
1422 * @return LY_ERR values.
1423 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001424static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001425parse_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 +02001426 struct lysp_ext_instance **exts)
1427{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001428 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001429 char *buf, *word;
Radek Krejci151a5b72018-10-19 14:21:44 +02001430 const char **item;
1431 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001432 enum yang_keyword kw;
1433
1434 /* allocate new pointer */
Radek Krejci2c4e7172018-10-19 15:56:26 +02001435 LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001436
1437 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001438 LY_CHECK_RET(get_argument(ctx, data, arg, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001439
Radek Krejci151a5b72018-10-19 14:21:44 +02001440 INSERT_WORD(ctx, buf, *item, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001441 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001442 switch (kw) {
1443 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001444 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_SIZE(*texts) - 1, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001445 break;
1446 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001447 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001448 return LY_EVALID;
1449 }
1450 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001451 return ret;
1452}
1453
Michal Vaskoea5abea2018-09-18 13:10:54 +02001454/**
1455 * @brief Parse the config statement.
1456 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001457 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001458 * @param[in,out] data Data to read from, always moved to currently handled character.
1459 * @param[in,out] flags Flags to add to.
1460 * @param[in,out] exts Extension instances to add to.
1461 *
1462 * @return LY_ERR values.
1463 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001464static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001465parse_config(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001466{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001467 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001468 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001469 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001470 enum yang_keyword kw;
1471
1472 if (*flags & LYS_CONFIG_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001473 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001474 return LY_EVALID;
1475 }
1476
1477 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001478 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001479
1480 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1481 *flags |= LYS_CONFIG_W;
1482 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1483 *flags |= LYS_CONFIG_R;
1484 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001485 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001486 free(buf);
1487 return LY_EVALID;
1488 }
1489 free(buf);
1490
Radek Krejci6d6556c2018-11-08 09:37:45 +01001491 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001492 switch (kw) {
1493 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001494 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001495 break;
1496 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001497 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001498 return LY_EVALID;
1499 }
1500 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001501 return ret;
1502}
1503
Michal Vaskoea5abea2018-09-18 13:10:54 +02001504/**
1505 * @brief Parse the mandatory statement.
1506 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001507 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001508 * @param[in,out] data Data to read from, always moved to currently handled character.
1509 * @param[in,out] flags Flags to add to.
1510 * @param[in,out] exts Extension instances to add to.
1511 *
1512 * @return LY_ERR values.
1513 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001514static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001515parse_mandatory(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001516{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001517 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001518 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001519 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001520 enum yang_keyword kw;
1521
1522 if (*flags & LYS_MAND_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001523 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001524 return LY_EVALID;
1525 }
1526
1527 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001528 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001529
1530 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
1531 *flags |= LYS_MAND_TRUE;
1532 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
1533 *flags |= LYS_MAND_FALSE;
1534 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001535 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001536 free(buf);
1537 return LY_EVALID;
1538 }
1539 free(buf);
1540
Radek Krejci6d6556c2018-11-08 09:37:45 +01001541 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001542 switch (kw) {
1543 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001544 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001545 break;
1546 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001547 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001548 return LY_EVALID;
1549 }
1550 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001551 return ret;
1552}
1553
Michal Vaskoea5abea2018-09-18 13:10:54 +02001554/**
1555 * @brief Parse a restriction such as range or length.
1556 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001557 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001558 * @param[in,out] data Data to read from, always moved to currently handled character.
1559 * @param[in] restr_kw Type of this particular restriction.
1560 * @param[in,out] exts Extension instances to add to.
1561 *
1562 * @return LY_ERR values.
1563 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001564static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001565parse_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 +02001566{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001567 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001568 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001569 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001570 enum yang_keyword kw;
1571
1572 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001573 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001574
Radek Krejci44ceedc2018-10-02 15:54:31 +02001575 INSERT_WORD(ctx, buf, restr->arg, word, word_len);
Radek Krejci6d6556c2018-11-08 09:37:45 +01001576 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001577 switch (kw) {
1578 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001579 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001580 break;
1581 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001582 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001583 break;
1584 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001585 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001586 break;
1587 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001588 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001589 break;
1590 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001591 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001592 break;
1593 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001594 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001595 return LY_EVALID;
1596 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001597 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001598 return ret;
1599}
1600
Michal Vaskoea5abea2018-09-18 13:10:54 +02001601/**
1602 * @brief Parse a restriction that can have more instances such as must.
1603 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001604 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001605 * @param[in,out] data Data to read from, always moved to currently handled character.
1606 * @param[in] restr_kw Type of this particular restriction.
1607 * @param[in,out] restrs Restrictions to add to.
1608 *
1609 * @return LY_ERR values.
1610 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001611static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001612parse_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 +02001613{
1614 struct lysp_restr *restr;
1615
Radek Krejci2c4e7172018-10-19 15:56:26 +02001616 LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001617 return parse_restr(ctx, data, restr_kw, restr);
1618}
1619
Michal Vaskoea5abea2018-09-18 13:10:54 +02001620/**
1621 * @brief Parse the status statement.
1622 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001623 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001624 * @param[in,out] data Data to read from, always moved to currently handled character.
1625 * @param[in,out] flags Flags to add to.
1626 * @param[in,out] exts Extension instances to add to.
1627 *
1628 * @return LY_ERR values.
1629 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001630static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001631parse_status(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001632{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001633 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001634 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001635 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001636 enum yang_keyword kw;
1637
1638 if (*flags & LYS_STATUS_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001639 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001640 return LY_EVALID;
1641 }
1642
1643 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001644 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001645
1646 if ((word_len == 7) && !strncmp(word, "current", word_len)) {
1647 *flags |= LYS_STATUS_CURR;
1648 } else if ((word_len == 10) && !strncmp(word, "deprecated", word_len)) {
1649 *flags |= LYS_STATUS_DEPRC;
1650 } else if ((word_len == 8) && !strncmp(word, "obsolete", word_len)) {
1651 *flags |= LYS_STATUS_OBSLT;
1652 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001653 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001654 free(buf);
1655 return LY_EVALID;
1656 }
1657 free(buf);
1658
Radek Krejci6d6556c2018-11-08 09:37:45 +01001659 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001660 switch (kw) {
1661 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001662 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001663 break;
1664 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001665 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001666 return LY_EVALID;
1667 }
1668 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001669 return ret;
1670}
1671
Michal Vaskoea5abea2018-09-18 13:10:54 +02001672/**
1673 * @brief Parse the when statement.
1674 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001675 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001676 * @param[in,out] data Data to read from, always moved to currently handled character.
1677 * @param[in,out] when_p When pointer to parse to.
1678 *
1679 * @return LY_ERR values.
1680 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001681static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001682parse_when(struct ly_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001683{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001684 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001685 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001686 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001687 enum yang_keyword kw;
1688 struct lysp_when *when;
1689
1690 if (*when_p) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001691 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001692 return LY_EVALID;
1693 }
1694
1695 when = calloc(1, sizeof *when);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001696 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001697 *when_p = when;
1698
1699 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001700 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001701 INSERT_WORD(ctx, buf, when->cond, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001702
Radek Krejci6d6556c2018-11-08 09:37:45 +01001703 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001704 switch (kw) {
1705 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001706 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001707 break;
1708 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001709 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001710 break;
1711 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001712 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001713 break;
1714 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001715 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001716 return LY_EVALID;
1717 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001718 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001719 return ret;
1720}
1721
Michal Vaskoea5abea2018-09-18 13:10:54 +02001722/**
1723 * @brief Parse the anydata or anyxml statement.
1724 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001725 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001726 * @param[in,out] data Data to read from, always moved to currently handled character.
1727 * @param[in] kw Type of this particular keyword.
1728 * @param[in,out] siblings Siblings to add to.
1729 *
1730 * @return LY_ERR values.
1731 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001732static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001733parse_any(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword kw, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001734{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001735 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001736 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02001737 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001738 struct lysp_node *iter;
1739 struct lysp_node_anydata *any;
1740
1741 /* create structure */
1742 any = calloc(1, sizeof *any);
Radek Krejci44ceedc2018-10-02 15:54:31 +02001743 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001744 any->nodetype = kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001745 any->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001746
1747 /* insert into siblings */
1748 if (!*siblings) {
1749 *siblings = (struct lysp_node *)any;
1750 } else {
1751 for (iter = *siblings; iter->next; iter = iter->next);
1752 iter->next = (struct lysp_node *)any;
1753 }
1754
1755 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001756 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02001757 INSERT_WORD(ctx, buf, any->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001758
1759 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01001760 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001761 switch (kw) {
1762 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001763 LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001764 break;
1765 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001766 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001767 break;
1768 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001769 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001770 break;
1771 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001772 LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001773 break;
1774 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001775 LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001776 break;
1777 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001778 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001779 break;
1780 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001781 LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001782 break;
1783 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001784 LY_CHECK_RET(parse_when(ctx, data, &any->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001785 break;
1786 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001787 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001788 break;
1789 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001790 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
Radek Krejcic59bc972018-09-17 16:13:06 +02001791 (any->nodetype & LYS_ANYDATA) == LYS_ANYDATA ? ly_stmt2str(YANG_ANYDATA) : ly_stmt2str(YANG_ANYXML));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001792 return LY_EVALID;
1793 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001794 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001795 return ret;
1796}
1797
Michal Vaskoea5abea2018-09-18 13:10:54 +02001798/**
1799 * @brief Parse the value or position statement. Substatement of type enum statement.
1800 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001801 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001802 * @param[in,out] data Data to read from, always moved to currently handled character.
1803 * @param[in] val_kw Type of this particular keyword.
1804 * @param[in,out] value Value to write to.
1805 * @param[in,out] flags Flags to write to.
1806 * @param[in,out] exts Extension instances to add to.
1807 *
1808 * @return LY_ERR values.
1809 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001810static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001811parse_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 +02001812 struct lysp_ext_instance **exts)
1813{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001814 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001815 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001816 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001817 long int num;
1818 unsigned long int unum;
1819 enum yang_keyword kw;
1820
1821 if (*flags & LYS_SET_VALUE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001822 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001823 return LY_EVALID;
1824 }
1825 *flags |= LYS_SET_VALUE;
1826
1827 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001828 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001829
1830 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 +02001831 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001832 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001833 }
1834
1835 errno = 0;
1836 if (val_kw == YANG_VALUE) {
1837 num = strtol(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001838 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
1839 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1840 goto error;
1841 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001842 } else {
1843 unum = strtoul(word, &ptr, 10);
Radek Krejci8b764662018-11-14 14:15:13 +01001844 if (unum > UINT64_C(4294967295)) {
1845 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
1846 goto error;
1847 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001848 }
1849 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001850 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001851 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001852 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001853 }
1854 if (errno == ERANGE) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001855 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, ly_stmt2str(val_kw));
Radek Krejci8b764662018-11-14 14:15:13 +01001856 goto error;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001857 }
1858 if (val_kw == YANG_VALUE) {
1859 *value = num;
1860 } else {
1861 *value = unum;
1862 }
1863 free(buf);
1864
Radek Krejci6d6556c2018-11-08 09:37:45 +01001865 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001866 switch (kw) {
1867 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001868 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, val_kw == YANG_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001869 break;
1870 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001871 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001872 return LY_EVALID;
1873 }
1874 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001875 return ret;
Radek Krejci8b764662018-11-14 14:15:13 +01001876
1877error:
1878 free(buf);
1879 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001880}
1881
Michal Vaskoea5abea2018-09-18 13:10:54 +02001882/**
1883 * @brief Parse the enum or bit statement. Substatement of type statement.
1884 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001885 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001886 * @param[in,out] data Data to read from, always moved to currently handled character.
1887 * @param[in] enum_kw Type of this particular keyword.
1888 * @param[in,out] enums Enums or bits to add to.
1889 *
1890 * @return LY_ERR values.
1891 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001892static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001893parse_type_enum(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 +02001894{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001895 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001896 char *buf, *word;
Radek Krejci8b764662018-11-14 14:15:13 +01001897 size_t word_len, u;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001898 enum yang_keyword kw;
1899 struct lysp_type_enum *enm;
1900
Radek Krejci2c4e7172018-10-19 15:56:26 +02001901 LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001902
1903 /* get value */
Radek Krejci8b764662018-11-14 14:15:13 +01001904 LY_CHECK_RET(get_argument(ctx, data, enum_kw == YANG_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, &word, &buf, &word_len));
1905 if (enum_kw == YANG_ENUM) {
1906 if (!word_len) {
1907 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not be zero-length.");
1908 free(buf);
1909 return LY_EVALID;
1910 } else if (isspace(word[0]) || isspace(word[word_len - 1])) {
1911 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Enum name must not have any leading or trailing whitespaces (\"%.*s\").",
1912 word_len, word);
1913 free(buf);
1914 return LY_EVALID;
1915 } else {
1916 for (u = 0; u < word_len; ++u) {
1917 if (iscntrl(word[u])) {
1918 LOGWRN(ctx->ctx, "Control characters in enum name should be avoided (\"%.*s\", character number %d).",
1919 word_len, word, u + 1);
1920 break;
1921 }
1922 }
1923 }
1924 } else { /* YANG_BIT */
1925
1926 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02001927 INSERT_WORD(ctx, buf, enm->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02001928
Radek Krejci8b764662018-11-14 14:15:13 +01001929 CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
1930
Radek Krejci6d6556c2018-11-08 09:37:45 +01001931 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02001932 switch (kw) {
1933 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001934 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001935 break;
1936 case YANG_IF_FEATURE:
Radek Krejci10113652018-11-14 16:56:50 +01001937 YANG_CHECK_STMTVER_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001938 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001939 break;
1940 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001941 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001942 break;
1943 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001944 LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001945 break;
1946 case YANG_VALUE:
1947 case YANG_POSITION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001948 LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001949 break;
1950 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001951 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001952 break;
1953 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02001954 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001955 return LY_EVALID;
1956 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001957 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02001958 return ret;
1959}
1960
Michal Vaskoea5abea2018-09-18 13:10:54 +02001961/**
1962 * @brief Parse the fraction-digits statement. Substatement of type statement.
1963 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02001964 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02001965 * @param[in,out] data Data to read from, always moved to currently handled character.
1966 * @param[in,out] fracdig Value to write to.
1967 * @param[in,out] exts Extension instances to add to.
1968 *
1969 * @return LY_ERR values.
1970 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02001971static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02001972parse_type_fracdigits(struct ly_parser_ctx *ctx, const char **data, uint8_t *fracdig, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02001973{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001974 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001975 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02001976 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02001977 unsigned long int num;
1978 enum yang_keyword kw;
1979
1980 if (*fracdig) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001981 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001982 return LY_EVALID;
1983 }
1984
1985 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01001986 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02001987
1988 if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001989 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001990 free(buf);
1991 return LY_EVALID;
1992 }
1993
1994 errno = 0;
1995 num = strtoul(word, &ptr, 10);
1996 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02001997 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02001998 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02001999 free(buf);
2000 return LY_EVALID;
2001 }
2002 if ((errno == ERANGE) || (num > 18)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002003 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002004 free(buf);
2005 return LY_EVALID;
2006 }
2007 *fracdig = num;
2008 free(buf);
2009
Radek Krejci6d6556c2018-11-08 09:37:45 +01002010 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002011 switch (kw) {
2012 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002013 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002014 break;
2015 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002016 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002017 return LY_EVALID;
2018 }
2019 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002020 return ret;
2021}
2022
Michal Vaskoea5abea2018-09-18 13:10:54 +02002023/**
2024 * @brief Parse the require-instance statement. Substatement of type statement.
2025 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002026 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002027 * @param[in,out] data Data to read from, always moved to currently handled character.
2028 * @param[in,out] reqinst Value to write to.
2029 * @param[in,out] flags Flags to write to.
2030 * @param[in,out] exts Extension instances to add to.
2031 *
2032 * @return LY_ERR values.
2033 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002034static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002035parse_type_reqinstance(struct ly_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
Michal Vasko7fbc8162018-09-17 10:35:16 +02002036 struct lysp_ext_instance **exts)
2037{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002038 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002039 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002040 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002041 enum yang_keyword kw;
2042
2043 if (*flags & LYS_SET_REQINST) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002044 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002045 return LY_EVALID;
2046 }
2047 *flags |= LYS_SET_REQINST;
2048
2049 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002050 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002051
2052 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
2053 *reqinst = 1;
2054 } else if ((word_len != 5) || strncmp(word, "false", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002055 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002056 free(buf);
2057 return LY_EVALID;
2058 }
2059 free(buf);
2060
Radek Krejci6d6556c2018-11-08 09:37:45 +01002061 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002062 switch (kw) {
2063 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002064 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002065 break;
2066 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002067 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002068 return LY_EVALID;
2069 }
2070 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002071 return ret;
2072}
2073
Michal Vaskoea5abea2018-09-18 13:10:54 +02002074/**
2075 * @brief Parse the modifier statement. Substatement of type pattern statement.
2076 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002077 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002078 * @param[in,out] data Data to read from, always moved to currently handled character.
2079 * @param[in,out] pat Value to write to.
2080 * @param[in,out] exts Extension instances to add to.
2081 *
2082 * @return LY_ERR values.
2083 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002084static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002085parse_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 +02002086{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002087 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002088 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002089 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002090 enum yang_keyword kw;
2091
2092 if ((*pat)[0] == 0x15) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002093 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002094 return LY_EVALID;
2095 }
2096
2097 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002098 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002099
2100 if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002101 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002102 free(buf);
2103 return LY_EVALID;
2104 }
2105 free(buf);
2106
2107 /* replace the value in the dictionary */
2108 buf = malloc(strlen(*pat) + 1);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002109 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002110 strcpy(buf, *pat);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002111 lydict_remove(ctx->ctx, *pat);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002112
2113 assert(buf[0] == 0x06);
2114 buf[0] = 0x15;
Radek Krejci44ceedc2018-10-02 15:54:31 +02002115 *pat = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002116
Radek Krejci6d6556c2018-11-08 09:37:45 +01002117 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002118 switch (kw) {
2119 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002120 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002121 break;
2122 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002123 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002124 return LY_EVALID;
2125 }
2126 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002127 return ret;
2128}
2129
Michal Vaskoea5abea2018-09-18 13:10:54 +02002130/**
2131 * @brief Parse the pattern statement. Substatement of type statement.
2132 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002133 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002134 * @param[in,out] data Data to read from, always moved to currently handled character.
2135 * @param[in,out] patterns Restrictions to add to.
2136 *
2137 * @return LY_ERR values.
2138 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002139static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002140parse_type_pattern(struct ly_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002141{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002142 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002143 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002144 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002145 enum yang_keyword kw;
2146 struct lysp_restr *restr;
2147
Radek Krejci2c4e7172018-10-19 15:56:26 +02002148 LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002149
2150 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002151 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002152
2153 /* add special meaning first byte */
2154 if (buf) {
2155 buf = realloc(buf, word_len + 2);
2156 word = buf;
2157 } else {
2158 buf = malloc(word_len + 2);
2159 }
Radek Krejci44ceedc2018-10-02 15:54:31 +02002160 LY_CHECK_ERR_RET(!buf, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci86d106e2018-10-18 09:53:19 +02002161 memmove(buf + 1, word, word_len);
2162 buf[0] = 0x06; /* pattern's default regular-match flag */
2163 buf[word_len + 1] = '\0'; /* terminating NULL byte */
2164 restr->arg = lydict_insert_zc(ctx->ctx, buf);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002165
Radek Krejci6d6556c2018-11-08 09:37:45 +01002166 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002167 switch (kw) {
2168 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002169 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002170 break;
2171 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002172 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002173 break;
2174 case YANG_ERROR_APP_TAG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002175 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002176 break;
2177 case YANG_ERROR_MESSAGE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002178 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002179 break;
2180 case YANG_MODIFIER:
Radek Krejci10113652018-11-14 16:56:50 +01002181 YANG_CHECK_STMTVER_RET(ctx, "modifier", "pattern");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002182 LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002183 break;
2184 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002185 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002186 break;
2187 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002188 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002189 return LY_EVALID;
2190 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002191 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002192 return ret;
2193}
2194
Michal Vaskoea5abea2018-09-18 13:10:54 +02002195/**
2196 * @brief Parse the type statement.
2197 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002198 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002199 * @param[in,out] data Data to read from, always moved to currently handled character.
2200 * @param[in,out] type Type to wrote to.
2201 *
2202 * @return LY_ERR values.
2203 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002204static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002205parse_type(struct ly_parser_ctx *ctx, const char **data, struct lysp_type *type)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002206{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002207 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002208 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002209 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002210 enum yang_keyword kw;
2211 struct lysp_type *nest_type;
2212
2213 if (type->name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002214 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002215 return LY_EVALID;
2216 }
2217
2218 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002219 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002220 INSERT_WORD(ctx, buf, type->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002221
Radek Krejci6d6556c2018-11-08 09:37:45 +01002222 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002223 switch (kw) {
2224 case YANG_BASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002225 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002226 type->flags |= LYS_SET_BASE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002227 break;
2228 case YANG_BIT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002229 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002230 type->flags |= LYS_SET_BIT;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002231 break;
2232 case YANG_ENUM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002233 LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002234 type->flags |= LYS_SET_ENUM;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002235 break;
2236 case YANG_FRACTION_DIGITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002237 LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002238 type->flags |= LYS_SET_FRDIGITS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002239 break;
2240 case YANG_LENGTH:
2241 if (type->length) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002242 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002243 return LY_EVALID;
2244 }
2245 type->length = calloc(1, sizeof *type->length);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002246 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002247
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002248 LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002249 type->flags |= LYS_SET_LENGTH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002250 break;
2251 case YANG_PATH:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002252 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &type->path, Y_STR_ARG, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002253 type->flags |= LYS_SET_PATH;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002254 break;
2255 case YANG_PATTERN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002256 LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002257 type->flags |= LYS_SET_PATTERN;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002258 break;
2259 case YANG_RANGE:
2260 if (type->range) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002261 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002262 return LY_EVALID;
2263 }
2264 type->range = calloc(1, sizeof *type->range);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002265 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002266
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002267 LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002268 type->flags |= LYS_SET_RANGE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002269 break;
2270 case YANG_REQUIRE_INSTANCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002271 LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002272 /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002273 break;
2274 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002275 LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
2276 LY_CHECK_RET(parse_type(ctx, data, nest_type));
Radek Krejcid505e3d2018-11-13 09:04:17 +01002277 type->flags |= LYS_SET_TYPE;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002278 break;
2279 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002280 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002281 break;
2282 default:
Radek Krejci8b764662018-11-14 14:15:13 +01002283 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002284 return LY_EVALID;
2285 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002286 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002287 return ret;
2288}
2289
Michal Vaskoea5abea2018-09-18 13:10:54 +02002290/**
2291 * @brief Parse the leaf statement.
2292 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002293 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002294 * @param[in,out] data Data to read from, always moved to currently handled character.
2295 * @param[in,out] siblings Siblings to add to.
2296 *
2297 * @return LY_ERR values.
2298 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002299static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002300parse_leaf(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002301{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002302 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002303 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002304 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002305 enum yang_keyword kw;
2306 struct lysp_node *iter;
2307 struct lysp_node_leaf *leaf;
2308
2309 /* create structure */
2310 leaf = calloc(1, sizeof *leaf);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002311 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002312 leaf->nodetype = LYS_LEAF;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002313 leaf->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002314
2315 /* insert into siblings */
2316 if (!*siblings) {
2317 *siblings = (struct lysp_node *)leaf;
2318 } else {
2319 for (iter = *siblings; iter->next; iter = iter->next);
2320 iter->next = (struct lysp_node *)leaf;
2321 }
2322
2323 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002324 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002325 INSERT_WORD(ctx, buf, leaf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002326
2327 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002328 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002329 switch (kw) {
2330 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002331 LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002332 break;
2333 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002334 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002335 break;
2336 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002337 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002338 break;
2339 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002340 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002341 break;
2342 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002343 LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002344 break;
2345 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002346 LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002347 break;
2348 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002349 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002350 break;
2351 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002352 LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002353 break;
2354 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002355 LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002356 break;
2357 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002358 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002359 break;
2360 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002361 LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002362 break;
2363 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002364 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002365 break;
2366 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002367 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002368 return LY_EVALID;
2369 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002370 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002371 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002372checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002373 /* mandatory substatements */
2374 if (!leaf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002375 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002376 return LY_EVALID;
2377 }
Radek Krejcib1a5dcc2018-11-26 14:50:05 +01002378 if ((leaf->flags & LYS_MAND_TRUE) && (leaf->dflt)) {
2379 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMSCOMB, "mandatory", "default", "leaf");
2380 return LY_EVALID;
2381 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002382
2383 return ret;
2384}
2385
Michal Vaskoea5abea2018-09-18 13:10:54 +02002386/**
2387 * @brief Parse the max-elements statement.
2388 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002389 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002390 * @param[in,out] data Data to read from, always moved to currently handled character.
2391 * @param[in,out] max Value to write to.
2392 * @param[in,out] flags Flags to write to.
2393 * @param[in,out] exts Extension instances to add to.
2394 *
2395 * @return LY_ERR values.
2396 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002397static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002398parse_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 +02002399{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002400 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002401 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002402 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002403 unsigned long int num;
2404 enum yang_keyword kw;
2405
2406 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002407 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002408 return LY_EVALID;
2409 }
2410 *flags |= LYS_SET_MAX;
2411
2412 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002413 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002414
2415 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002416 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002417 free(buf);
2418 return LY_EVALID;
2419 }
2420
2421 if (strncmp(word, "unbounded", word_len)) {
2422 errno = 0;
2423 num = strtoul(word, &ptr, 10);
2424 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002425 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002426 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002427 free(buf);
2428 return LY_EVALID;
2429 }
2430 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002431 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002432 free(buf);
2433 return LY_EVALID;
2434 }
2435
2436 *max = num;
2437 }
2438 free(buf);
2439
Radek Krejci6d6556c2018-11-08 09:37:45 +01002440 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002441 switch (kw) {
2442 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002443 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002444 break;
2445 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002446 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002447 return LY_EVALID;
2448 }
2449 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002450 return ret;
2451}
2452
Michal Vaskoea5abea2018-09-18 13:10:54 +02002453/**
2454 * @brief Parse the min-elements statement.
2455 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002456 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002457 * @param[in,out] data Data to read from, always moved to currently handled character.
2458 * @param[in,out] min Value to write to.
2459 * @param[in,out] flags Flags to write to.
2460 * @param[in,out] exts Extension instances to add to.
2461 *
2462 * @return LY_ERR values.
2463 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002464static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002465parse_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 +02002466{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002467 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002468 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002469 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002470 unsigned long int num;
2471 enum yang_keyword kw;
2472
2473 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002474 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002475 return LY_EVALID;
2476 }
2477 *flags |= LYS_SET_MIN;
2478
2479 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002480 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002481
2482 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002483 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002484 free(buf);
2485 return LY_EVALID;
2486 }
2487
2488 errno = 0;
2489 num = strtoul(word, &ptr, 10);
2490 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002491 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002492 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002493 free(buf);
2494 return LY_EVALID;
2495 }
2496 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002497 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002498 free(buf);
2499 return LY_EVALID;
2500 }
2501 *min = num;
2502 free(buf);
2503
Radek Krejci6d6556c2018-11-08 09:37:45 +01002504 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002505 switch (kw) {
2506 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002507 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002508 break;
2509 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002510 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002511 return LY_EVALID;
2512 }
2513 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002514 return ret;
2515}
2516
Michal Vaskoea5abea2018-09-18 13:10:54 +02002517/**
2518 * @brief Parse the ordered-by statement.
2519 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002520 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002521 * @param[in,out] data Data to read from, always moved to currently handled character.
2522 * @param[in,out] flags Flags to write to.
2523 * @param[in,out] exts Extension instances to add to.
2524 *
2525 * @return LY_ERR values.
2526 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002527static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002528parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002529{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002530 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002531 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002532 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002533 enum yang_keyword kw;
2534
2535 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002536 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002537 return LY_EVALID;
2538 }
2539
2540 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002541 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002542
2543 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2544 *flags |= LYS_ORDBY_SYSTEM;
2545 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2546 *flags |= LYS_ORDBY_USER;
2547 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002548 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002549 free(buf);
2550 return LY_EVALID;
2551 }
2552 free(buf);
2553
Radek Krejci6d6556c2018-11-08 09:37:45 +01002554 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002555 switch (kw) {
2556 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002557 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002558 break;
2559 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002560 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002561 return LY_EVALID;
2562 }
2563 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002564 return ret;
2565}
2566
Michal Vaskoea5abea2018-09-18 13:10:54 +02002567/**
2568 * @brief Parse the leaf-list statement.
2569 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002570 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002571 * @param[in,out] data Data to read from, always moved to currently handled character.
2572 * @param[in,out] siblings Siblings to add to.
2573 *
2574 * @return LY_ERR values.
2575 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002576static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002577parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002578{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002579 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002580 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002581 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002582 enum yang_keyword kw;
2583 struct lysp_node *iter;
2584 struct lysp_node_leaflist *llist;
2585
2586 /* create structure */
2587 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002588 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002589 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002590 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002591
2592 /* insert into siblings */
2593 if (!*siblings) {
2594 *siblings = (struct lysp_node *)llist;
2595 } else {
2596 for (iter = *siblings; iter->next; iter = iter->next);
2597 iter->next = (struct lysp_node *)llist;
2598 }
2599
2600 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002601 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002602 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002603
2604 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002605 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002606 switch (kw) {
2607 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002608 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002609 break;
2610 case YANG_DEFAULT:
Radek Krejci10113652018-11-14 16:56:50 +01002611 YANG_CHECK_STMTVER_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002612 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002613 break;
2614 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002615 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002616 break;
2617 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002618 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002619 break;
2620 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002621 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002622 break;
2623 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002624 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002625 break;
2626 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002627 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002628 break;
2629 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002630 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002631 break;
2632 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002633 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002634 break;
2635 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002636 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002637 break;
2638 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002639 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002640 break;
2641 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002642 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002643 break;
2644 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002645 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002646 break;
2647 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002648 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002649 break;
2650 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002651 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002652 return LY_EVALID;
2653 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002654 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002655 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002656checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002657 /* mandatory substatements */
2658 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002659 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002660 return LY_EVALID;
2661 }
2662
2663 return ret;
2664}
2665
Michal Vaskoea5abea2018-09-18 13:10:54 +02002666/**
2667 * @brief Parse the refine statement.
2668 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002669 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002670 * @param[in,out] data Data to read from, always moved to currently handled character.
2671 * @param[in,out] refines Refines to add to.
2672 *
2673 * @return LY_ERR values.
2674 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002675static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002676parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002677{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002678 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002679 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002680 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002681 enum yang_keyword kw;
2682 struct lysp_refine *rf;
2683
Radek Krejci2c4e7172018-10-19 15:56:26 +02002684 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002685
2686 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002687 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002688 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002689
Radek Krejci6d6556c2018-11-08 09:37:45 +01002690 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002691 switch (kw) {
2692 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002693 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002694 break;
2695 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002696 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002697 break;
2698 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002699 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002700 break;
2701 case YANG_IF_FEATURE:
Radek Krejci10113652018-11-14 16:56:50 +01002702 YANG_CHECK_STMTVER_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002703 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002704 break;
2705 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002706 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002707 break;
2708 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002709 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002710 break;
2711 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002712 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002713 break;
2714 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002715 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002716 break;
2717 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002718 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002719 break;
2720 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002721 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002722 break;
2723 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002724 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002725 break;
2726 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002727 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002728 return LY_EVALID;
2729 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002730 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002731 return ret;
2732}
2733
Michal Vaskoea5abea2018-09-18 13:10:54 +02002734/**
2735 * @brief Parse the typedef statement.
2736 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002737 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002738 * @param[in,out] data Data to read from, always moved to currently handled character.
2739 * @param[in,out] typedefs Typedefs to add to.
2740 *
2741 * @return LY_ERR values.
2742 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002743static LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01002744parse_typedef(struct ly_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002745{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002746 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002747 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002748 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002749 enum yang_keyword kw;
2750 struct lysp_tpdf *tpdf;
2751
Radek Krejci2c4e7172018-10-19 15:56:26 +02002752 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002753
2754 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002755 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002756 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002757
2758 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002759 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002760 switch (kw) {
2761 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002762 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002763 break;
2764 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002765 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002766 break;
2767 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002768 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002769 break;
2770 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002771 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002772 break;
2773 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002774 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002775 break;
2776 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002777 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002778 break;
2779 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002780 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002781 break;
2782 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002783 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002784 return LY_EVALID;
2785 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002786 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002787 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002788checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002789 /* mandatory substatements */
2790 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002791 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002792 return LY_EVALID;
2793 }
2794
Radek Krejcibbe09a92018-11-08 09:36:54 +01002795 /* store data for collision check */
2796 if (parent) {
2797 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2798 }
2799
Michal Vasko7fbc8162018-09-17 10:35:16 +02002800 return ret;
2801}
2802
Michal Vaskoea5abea2018-09-18 13:10:54 +02002803/**
2804 * @brief Parse the input or output statement.
2805 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002806 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002807 * @param[in,out] data Data to read from, always moved to currently handled character.
2808 * @param[in] kw Type of this particular keyword
2809 * @param[in,out] inout_p Input/output pointer to write to.
2810 *
2811 * @return LY_ERR values.
2812 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002813static LY_ERR
Radek Krejci10113652018-11-14 16:56:50 +01002814parse_inout(struct ly_parser_ctx *ctx, const char **data, enum yang_keyword inout_kw, struct lysp_node *parent, struct lysp_action_inout **inout_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002815{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002816 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002817 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002818 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002819 struct lysp_action_inout *inout;
Radek Krejci10113652018-11-14 16:56:50 +01002820 enum yang_keyword kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002821
2822 if (*inout_p) {
Radek Krejci10113652018-11-14 16:56:50 +01002823 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002824 return LY_EVALID;
2825 }
2826
2827 /* create structure */
2828 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002829 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002830 *inout_p = inout;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002831 inout->nodetype = LYS_INOUT;
2832 inout->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002833
2834 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002835 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002836 switch (kw) {
2837 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01002838 YANG_CHECK_STMTVER_RET(ctx, "anydata", ly_stmt2str(inout_kw));
2839 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002840 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002841 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002842 break;
2843 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002844 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002845 break;
2846 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002847 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002848 break;
2849 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002850 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002851 break;
2852 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002853 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002854 break;
2855 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002856 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 break;
2858 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002859 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002860 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002861 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002862 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout, data, &inout->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863 break;
2864 case YANG_MUST:
Radek Krejci10113652018-11-14 16:56:50 +01002865 YANG_CHECK_STMTVER_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002866 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002867 break;
2868 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002869 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout, &inout->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002870 break;
2871 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002872 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002873 break;
2874 default:
Radek Krejci10113652018-11-14 16:56:50 +01002875 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002876 return LY_EVALID;
2877 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002878 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002879 return ret;
2880}
2881
Michal Vaskoea5abea2018-09-18 13:10:54 +02002882/**
2883 * @brief Parse the action statement.
2884 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002885 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002886 * @param[in,out] data Data to read from, always moved to currently handled character.
2887 * @param[in,out] actions Actions to add to.
2888 *
2889 * @return LY_ERR values.
2890 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002891static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002892parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002893{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002894 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002895 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002896 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002897 enum yang_keyword kw;
2898 struct lysp_action *act;
2899
Radek Krejci2c4e7172018-10-19 15:56:26 +02002900 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002901
2902 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002903 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002904 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002905 act->nodetype = LYS_ACTION;
2906 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002907
Radek Krejci6d6556c2018-11-08 09:37:45 +01002908 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002909 switch (kw) {
2910 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002911 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002912 break;
2913 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002914 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002915 break;
2916 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002917 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002918 break;
2919 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002920 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002921 break;
2922
2923 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002924 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002925 break;
2926 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002927 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002928 break;
2929
2930 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002931 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002932 break;
2933 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002934 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002935 break;
2936 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002937 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002938 break;
2939 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002940 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002941 return LY_EVALID;
2942 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002943 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002944 return ret;
2945}
2946
Michal Vaskoea5abea2018-09-18 13:10:54 +02002947/**
2948 * @brief Parse the notification statement.
2949 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002950 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002951 * @param[in,out] data Data to read from, always moved to currently handled character.
2952 * @param[in,out] notifs Notifications to add to.
2953 *
2954 * @return LY_ERR values.
2955 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002956static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002957parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002958{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002959 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002960 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002961 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002962 enum yang_keyword kw;
2963 struct lysp_notif *notif;
2964
Radek Krejci2c4e7172018-10-19 15:56:26 +02002965 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002966
2967 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002968 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002969 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002970 notif->nodetype = LYS_NOTIF;
2971 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002972
Radek Krejci6d6556c2018-11-08 09:37:45 +01002973 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002974 switch (kw) {
2975 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002976 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002977 break;
2978 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002979 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002980 break;
2981 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002982 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002983 break;
2984 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002985 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002986 break;
2987
2988 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01002989 YANG_CHECK_STMTVER_RET(ctx, "anydata", "notification");
2990 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002991 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002992 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002993 break;
2994 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002995 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002996 break;
2997 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002998 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002999 break;
3000 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003001 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003002 break;
3003 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003004 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003005 break;
3006 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003007 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003008 break;
3009 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003010 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003011 break;
3012
3013 case YANG_MUST:
Radek Krejci10113652018-11-14 16:56:50 +01003014 YANG_CHECK_STMTVER_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003015 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003016 break;
3017 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003018 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003019 break;
3020 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003021 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003022 break;
3023 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003024 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003025 break;
3026 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003027 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003028 return LY_EVALID;
3029 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003030 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003031 return ret;
3032}
3033
Michal Vaskoea5abea2018-09-18 13:10:54 +02003034/**
3035 * @brief Parse the grouping statement.
3036 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003037 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003038 * @param[in,out] data Data to read from, always moved to currently handled character.
3039 * @param[in,out] groupings Groupings to add to.
3040 *
3041 * @return LY_ERR values.
3042 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003043static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003044parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003045{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003046 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003047 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003048 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003049 enum yang_keyword kw;
3050 struct lysp_grp *grp;
3051
Radek Krejci2c4e7172018-10-19 15:56:26 +02003052 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003053
3054 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003055 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003056 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003057 grp->nodetype = LYS_GROUPING;
3058 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003059
Radek Krejci6d6556c2018-11-08 09:37:45 +01003060 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003061 switch (kw) {
3062 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003063 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003064 break;
3065 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003066 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003067 break;
3068 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003069 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003070 break;
3071
3072 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003073 YANG_CHECK_STMTVER_RET(ctx, "anydata", "grouping");
3074 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003075 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003076 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003077 break;
3078 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003079 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003080 break;
3081 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003082 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003083 break;
3084 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003085 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003086 break;
3087 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003088 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003089 break;
3090 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003091 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003092 break;
3093 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003094 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003095 break;
3096
3097 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003098 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003099 break;
3100 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003101 YANG_CHECK_STMTVER_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003102 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003103 break;
3104 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003105 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003106 break;
3107 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003108 YANG_CHECK_STMTVER_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003109 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003110 break;
3111 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003112 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003113 break;
3114 default:
Radek Krejci10113652018-11-14 16:56:50 +01003115 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003116 return LY_EVALID;
3117 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003118 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003119 return ret;
3120}
3121
Michal Vaskoea5abea2018-09-18 13:10:54 +02003122/**
3123 * @brief Parse the refine statement.
3124 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003125 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003126 * @param[in,out] data Data to read from, always moved to currently handled character.
3127 * @param[in,out] augments Augments to add to.
3128 *
3129 * @return LY_ERR values.
3130 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003131static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003132parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003133{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003134 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003135 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003136 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003137 enum yang_keyword kw;
3138 struct lysp_augment *aug;
3139
Radek Krejci2c4e7172018-10-19 15:56:26 +02003140 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003141
3142 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003143 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003144 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003145 aug->nodetype = LYS_AUGMENT;
3146 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003147
Radek Krejci6d6556c2018-11-08 09:37:45 +01003148 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003149 switch (kw) {
3150 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003151 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003152 break;
3153 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003154 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003155 break;
3156 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003157 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003158 break;
3159 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003160 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003161 break;
3162 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003163 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003164 break;
3165
3166 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003167 YANG_CHECK_STMTVER_RET(ctx, "anydata", "augment");
3168 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003169 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003170 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003171 break;
3172 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003173 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003174 break;
3175 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003176 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003177 break;
3178 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003179 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003180 break;
3181 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003182 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003183 break;
3184 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003185 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003186 break;
3187 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003188 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003189 break;
3190 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003191 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003192 break;
3193
3194 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003195 YANG_CHECK_STMTVER_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003196 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003197 break;
3198 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003199 YANG_CHECK_STMTVER_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003200 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003201 break;
3202 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003203 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003204 break;
3205 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003206 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003207 return LY_EVALID;
3208 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003209 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003210 return ret;
3211}
3212
Michal Vaskoea5abea2018-09-18 13:10:54 +02003213/**
3214 * @brief Parse the uses statement.
3215 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003216 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003217 * @param[in,out] data Data to read from, always moved to currently handled character.
3218 * @param[in,out] siblings Siblings to add to.
3219 *
3220 * @return LY_ERR values.
3221 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003222static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003223parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003225 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003226 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003227 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003228 enum yang_keyword kw;
3229 struct lysp_node *iter;
3230 struct lysp_node_uses *uses;
3231
3232 /* create structure */
3233 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003234 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003235 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003236 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003237
3238 /* insert into siblings */
3239 if (!*siblings) {
3240 *siblings = (struct lysp_node *)uses;
3241 } else {
3242 for (iter = *siblings; iter->next; iter = iter->next);
3243 iter->next = (struct lysp_node *)uses;
3244 }
3245
3246 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003247 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003248 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003249
3250 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003251 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003252 switch (kw) {
3253 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003254 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003255 break;
3256 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003257 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003258 break;
3259 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003260 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003261 break;
3262 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003263 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003264 break;
3265 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003266 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003267 break;
3268
3269 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003270 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003271 break;
3272 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003273 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003274 break;
3275 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003276 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003277 break;
3278 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003279 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003280 return LY_EVALID;
3281 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003282 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003283 return ret;
3284}
3285
Michal Vaskoea5abea2018-09-18 13:10:54 +02003286/**
3287 * @brief Parse the case statement.
3288 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003289 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003290 * @param[in,out] data Data to read from, always moved to currently handled character.
3291 * @param[in,out] siblings Siblings to add to.
3292 *
3293 * @return LY_ERR values.
3294 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003295static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003296parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003298 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003299 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003300 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003301 enum yang_keyword kw;
3302 struct lysp_node *iter;
3303 struct lysp_node_case *cas;
3304
3305 /* create structure */
3306 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003307 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003308 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003309 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003310
3311 /* insert into siblings */
3312 if (!*siblings) {
3313 *siblings = (struct lysp_node *)cas;
3314 } else {
3315 for (iter = *siblings; iter->next; iter = iter->next);
3316 iter->next = (struct lysp_node *)cas;
3317 }
3318
3319 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003320 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003321 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003322
3323 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003324 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003325 switch (kw) {
3326 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003327 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003328 break;
3329 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003330 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003331 break;
3332 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003333 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003334 break;
3335 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003336 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003337 break;
3338 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003339 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003340 break;
3341
3342 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003343 YANG_CHECK_STMTVER_RET(ctx, "anydata", "case");
3344 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003345 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003346 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003347 break;
3348 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003349 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003350 break;
3351 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003352 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003353 break;
3354 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003355 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003356 break;
3357 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003358 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003359 break;
3360 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003361 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003362 break;
3363 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003364 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003365 break;
3366 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003367 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003368 break;
3369 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003370 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003371 return LY_EVALID;
3372 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003373 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003374 return ret;
3375}
3376
Michal Vaskoea5abea2018-09-18 13:10:54 +02003377/**
3378 * @brief Parse the choice statement.
3379 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003380 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003381 * @param[in,out] data Data to read from, always moved to currently handled character.
3382 * @param[in,out] siblings Siblings to add to.
3383 *
3384 * @return LY_ERR values.
3385 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003386static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003387parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003388{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003389 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003390 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003391 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003392 enum yang_keyword kw;
3393 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003394 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003395
3396 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003397 choice = calloc(1, sizeof *choice);
3398 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3399 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003400 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003401
3402 /* insert into siblings */
3403 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003404 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003405 } else {
3406 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003407 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003408 }
3409
3410 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003411 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003412 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003413
3414 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003415 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003416 switch (kw) {
3417 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003418 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003419 break;
3420 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003421 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003422 break;
3423 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003424 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003425 break;
3426 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003427 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003428 break;
3429 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003430 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003431 break;
3432 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003433 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003434 break;
3435 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003436 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003437 break;
3438 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003439 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_IDENTIF_ARG, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003440 break;
3441
3442 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003443 YANG_CHECK_STMTVER_RET(ctx, "anydata", "choice");
3444 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003445 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003446 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003447 break;
3448 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003449 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003450 break;
3451 case YANG_CHOICE:
Radek Krejci10113652018-11-14 16:56:50 +01003452 YANG_CHECK_STMTVER_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003453 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003454 break;
3455 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003456 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003457 break;
3458 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003459 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003460 break;
3461 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003462 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003463 break;
3464 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003465 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003466 break;
3467 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003468 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003469 break;
3470 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003471 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003472 return LY_EVALID;
3473 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003474 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003475 return ret;
3476}
3477
Michal Vaskoea5abea2018-09-18 13:10:54 +02003478/**
3479 * @brief Parse the container statement.
3480 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003481 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003482 * @param[in,out] data Data to read from, always moved to currently handled character.
3483 * @param[in,out] siblings Siblings to add to.
3484 *
3485 * @return LY_ERR values.
3486 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003487static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003488parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003489{
3490 LY_ERR ret = 0;
3491 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003492 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003493 enum yang_keyword kw;
3494 struct lysp_node *iter;
3495 struct lysp_node_container *cont;
3496
3497 /* create structure */
3498 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003499 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003500 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003501 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003502
3503 /* insert into siblings */
3504 if (!*siblings) {
3505 *siblings = (struct lysp_node *)cont;
3506 } else {
3507 for (iter = *siblings; iter->next; iter = iter->next);
3508 iter->next = (struct lysp_node *)cont;
3509 }
3510
3511 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003512 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003513 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003514
3515 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003516 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003517 switch (kw) {
3518 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003519 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003520 break;
3521 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003522 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003523 break;
3524 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003525 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003526 break;
3527 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003528 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003529 break;
3530 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003531 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003532 break;
3533 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003534 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003535 break;
3536 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003537 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003538 break;
3539
3540 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003541 YANG_CHECK_STMTVER_RET(ctx, "anydata", "container");
3542 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003543 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003544 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003545 break;
3546 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003547 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003548 break;
3549 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003550 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003551 break;
3552 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003553 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003554 break;
3555 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003556 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003557 break;
3558 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003559 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003560 break;
3561 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003562 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003563 break;
3564
3565 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003566 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003567 break;
3568 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003569 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003570 break;
3571 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003572 YANG_CHECK_STMTVER_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003573 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003574 break;
3575 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003576 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003577 break;
3578 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003579 YANG_CHECK_STMTVER_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003580 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003581 break;
3582 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003583 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003584 break;
3585 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003586 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003587 return LY_EVALID;
3588 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003589 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003590 return ret;
3591}
3592
Michal Vaskoea5abea2018-09-18 13:10:54 +02003593/**
3594 * @brief Parse the list statement.
3595 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003596 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003597 * @param[in,out] data Data to read from, always moved to currently handled character.
3598 * @param[in,out] siblings Siblings to add to.
3599 *
3600 * @return LY_ERR values.
3601 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003602static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003603parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003604{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003605 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003606 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003607 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003608 enum yang_keyword kw;
3609 struct lysp_node *iter;
3610 struct lysp_node_list *list;
3611
3612 /* create structure */
3613 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003614 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003615 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003616 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003617
3618 /* insert into siblings */
3619 if (!*siblings) {
3620 *siblings = (struct lysp_node *)list;
3621 } else {
3622 for (iter = *siblings; iter->next; iter = iter->next);
3623 iter->next = (struct lysp_node *)list;
3624 }
3625
3626 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003627 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003628 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003629
3630 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003631 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003632 switch (kw) {
3633 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003634 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003635 break;
3636 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003637 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003638 break;
3639 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003640 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003641 break;
3642 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003643 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003644 break;
3645 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003646 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003647 break;
3648 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003649 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003650 break;
3651 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003652 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003653 break;
3654 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003655 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003656 break;
3657 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003658 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003659 break;
3660 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003661 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003662 break;
3663 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003664 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003665 break;
3666
3667 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003668 YANG_CHECK_STMTVER_RET(ctx, "anydata", "list");
3669 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003670 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003671 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003672 break;
3673 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003674 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003675 break;
3676 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003677 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003678 break;
3679 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003680 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003681 break;
3682 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003683 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003684 break;
3685 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003686 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003687 break;
3688 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003689 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003690 break;
3691
3692 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003693 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003694 break;
3695 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003696 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003697 break;
3698 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003699 YANG_CHECK_STMTVER_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003700 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003701 break;
3702 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003703 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003704 break;
3705 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003706 YANG_CHECK_STMTVER_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003707 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003708 break;
3709 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003710 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003711 break;
3712 default:
Radek Krejci10113652018-11-14 16:56:50 +01003713 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003714 return LY_EVALID;
3715 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003716 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003717
3718 return ret;
3719}
3720
Michal Vaskoea5abea2018-09-18 13:10:54 +02003721/**
3722 * @brief Parse the yin-element statement.
3723 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003724 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003725 * @param[in,out] data Data to read from, always moved to currently handled character.
3726 * @param[in,out] flags Flags to write to.
3727 * @param[in,out] exts Extension instances to add to.
3728 *
3729 * @return LY_ERR values.
3730 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003731static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003732parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003733{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003734 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003735 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003736 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003737 enum yang_keyword kw;
3738
3739 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003740 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003741 return LY_EVALID;
3742 }
3743
3744 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003745 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003746
3747 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3748 *flags |= LYS_YINELEM_TRUE;
3749 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3750 *flags |= LYS_YINELEM_FALSE;
3751 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003752 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003753 free(buf);
3754 return LY_EVALID;
3755 }
3756 free(buf);
3757
Radek Krejci6d6556c2018-11-08 09:37:45 +01003758 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003759 switch (kw) {
3760 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003761 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3762 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003763 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003764 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003765 return LY_EVALID;
3766 }
3767 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003768 return ret;
3769}
3770
Michal Vaskoea5abea2018-09-18 13:10:54 +02003771/**
3772 * @brief Parse the yin-element statement.
3773 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003774 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003775 * @param[in,out] data Data to read from, always moved to currently handled character.
3776 * @param[in,out] argument Value to write to.
3777 * @param[in,out] flags Flags to write to.
3778 * @param[in,out] exts Extension instances to add to.
3779 *
3780 * @return LY_ERR values.
3781 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003782static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003783parse_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 +02003784{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003785 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003786 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003787 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003788 enum yang_keyword kw;
3789
3790 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003791 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003792 return LY_EVALID;
3793 }
3794
3795 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003796 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003797 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003798
Radek Krejci6d6556c2018-11-08 09:37:45 +01003799 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003800 switch (kw) {
3801 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003802 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003803 break;
3804 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003805 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003806 break;
3807 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003808 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003809 return LY_EVALID;
3810 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003811 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003812 return ret;
3813}
3814
Michal Vaskoea5abea2018-09-18 13:10:54 +02003815/**
3816 * @brief Parse the extension statement.
3817 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003818 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003819 * @param[in,out] data Data to read from, always moved to currently handled character.
3820 * @param[in,out] extensions Extensions to add to.
3821 *
3822 * @return LY_ERR values.
3823 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003824static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003825parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003826{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003827 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003828 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003829 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003830 enum yang_keyword kw;
3831 struct lysp_ext *ex;
3832
Radek Krejci2c4e7172018-10-19 15:56:26 +02003833 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003834
3835 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003836 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003837 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003838
Radek Krejci6d6556c2018-11-08 09:37:45 +01003839 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003840 switch (kw) {
3841 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003842 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003843 break;
3844 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003845 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003846 break;
3847 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003848 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003849 break;
3850 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003851 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003852 break;
3853 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003854 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003855 break;
3856 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003857 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003858 return LY_EVALID;
3859 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003860 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003861 return ret;
3862}
3863
Michal Vaskoea5abea2018-09-18 13:10:54 +02003864/**
3865 * @brief Parse the deviate statement.
3866 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003867 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003868 * @param[in,out] data Data to read from, always moved to currently handled character.
3869 * @param[in,out] deviates Deviates to add to.
3870 *
3871 * @return LY_ERR values.
3872 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003873static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003874parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003875{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003876 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003877 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003878 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003879 enum yang_keyword kw;
3880 struct lysp_deviate *iter, *d;
3881 struct lysp_deviate_add *d_add = NULL;
3882 struct lysp_deviate_rpl *d_rpl = NULL;
3883 struct lysp_deviate_del *d_del = NULL;
3884 const char **d_units, ***d_uniques, ***d_dflts;
3885 struct lysp_restr **d_musts;
3886 uint16_t *d_flags;
3887 uint32_t *d_min, *d_max;
3888
3889 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003890 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003891
3892 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3893 dev_mod = LYS_DEV_NOT_SUPPORTED;
3894 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3895 dev_mod = LYS_DEV_ADD;
3896 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3897 dev_mod = LYS_DEV_REPLACE;
3898 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3899 dev_mod = LYS_DEV_DELETE;
3900 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003901 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003902 free(buf);
3903 return LY_EVALID;
3904 }
3905 free(buf);
3906
3907 /* create structure */
3908 switch (dev_mod) {
3909 case LYS_DEV_NOT_SUPPORTED:
3910 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003911 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003912 break;
3913 case LYS_DEV_ADD:
3914 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003915 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003916 d = (struct lysp_deviate *)d_add;
3917 d_units = &d_add->units;
3918 d_uniques = &d_add->uniques;
3919 d_dflts = &d_add->dflts;
3920 d_musts = &d_add->musts;
3921 d_flags = &d_add->flags;
3922 d_min = &d_add->min;
3923 d_max = &d_add->max;
3924 break;
3925 case LYS_DEV_REPLACE:
3926 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003927 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003928 d = (struct lysp_deviate *)d_rpl;
3929 d_units = &d_rpl->units;
3930 d_flags = &d_rpl->flags;
3931 d_min = &d_rpl->min;
3932 d_max = &d_rpl->max;
3933 break;
3934 case LYS_DEV_DELETE:
3935 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003936 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003937 d = (struct lysp_deviate *)d_del;
3938 d_units = &d_del->units;
3939 d_uniques = &d_del->uniques;
3940 d_dflts = &d_del->dflts;
3941 d_musts = &d_del->musts;
3942 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003943 break;
3944 default:
3945 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003946 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003947 }
3948 d->mod = dev_mod;
3949
3950 /* insert into siblings */
3951 if (!*deviates) {
3952 *deviates = d;
3953 } else {
3954 for (iter = *deviates; iter->next; iter = iter->next);
3955 iter->next = d;
3956 }
3957
Radek Krejci6d6556c2018-11-08 09:37:45 +01003958 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003959 switch (kw) {
3960 case YANG_CONFIG:
3961 switch (dev_mod) {
3962 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003963 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003964 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003965 return LY_EVALID;
3966 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003967 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003968 break;
3969 }
3970 break;
3971 case YANG_DEFAULT:
3972 switch (dev_mod) {
3973 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003974 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003975 return LY_EVALID;
3976 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003977 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003978 break;
3979 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003980 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003981 break;
3982 }
3983 break;
3984 case YANG_MANDATORY:
3985 switch (dev_mod) {
3986 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003987 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003988 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003989 return LY_EVALID;
3990 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003991 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003992 break;
3993 }
3994 break;
3995 case YANG_MAX_ELEMENTS:
3996 switch (dev_mod) {
3997 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003998 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003999 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004000 return LY_EVALID;
4001 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004002 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004003 break;
4004 }
4005 break;
4006 case YANG_MIN_ELEMENTS:
4007 switch (dev_mod) {
4008 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004009 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004010 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004011 return LY_EVALID;
4012 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004013 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004014 break;
4015 }
4016 break;
4017 case YANG_MUST:
4018 switch (dev_mod) {
4019 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004020 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004021 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004022 return LY_EVALID;
4023 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004024 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004025 break;
4026 }
4027 break;
4028 case YANG_TYPE:
4029 switch (dev_mod) {
4030 case LYS_DEV_NOT_SUPPORTED:
4031 case LYS_DEV_ADD:
4032 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004033 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004034 return LY_EVALID;
4035 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004036 if (d_rpl->type) {
4037 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4038 return LY_EVALID;
4039 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004040 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004041 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004042 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004043 break;
4044 }
4045 break;
4046 case YANG_UNIQUE:
4047 switch (dev_mod) {
4048 case LYS_DEV_NOT_SUPPORTED:
4049 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004050 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004051 return LY_EVALID;
4052 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004053 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004054 break;
4055 }
4056 break;
4057 case YANG_UNITS:
4058 switch (dev_mod) {
4059 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004060 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004061 return LY_EVALID;
4062 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004063 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004064 break;
4065 }
4066 break;
4067 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004068 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004069 break;
4070 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004071 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004072 return LY_EVALID;
4073 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004074 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004075 return ret;
4076}
4077
Michal Vaskoea5abea2018-09-18 13:10:54 +02004078/**
4079 * @brief Parse the deviation statement.
4080 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004081 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004082 * @param[in,out] data Data to read from, always moved to currently handled character.
4083 * @param[in,out] deviations Deviations to add to.
4084 *
4085 * @return LY_ERR values.
4086 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004087static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004088parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004089{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004090 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004091 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004092 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004093 enum yang_keyword kw;
4094 struct lysp_deviation *dev;
4095
Radek Krejci2c4e7172018-10-19 15:56:26 +02004096 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004097
4098 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004099 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004100 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004101
Radek Krejci6d6556c2018-11-08 09:37:45 +01004102 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004103 switch (kw) {
4104 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004105 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004106 break;
4107 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004108 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004109 break;
4110 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004111 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004112 break;
4113 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004114 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004115 break;
4116 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004117 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004118 return LY_EVALID;
4119 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004120 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004121 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004122checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004123 /* mandatory substatements */
4124 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004125 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004126 return LY_EVALID;
4127 }
4128
4129 return ret;
4130}
4131
Michal Vaskoea5abea2018-09-18 13:10:54 +02004132/**
4133 * @brief Parse the feature statement.
4134 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004135 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004136 * @param[in,out] data Data to read from, always moved to currently handled character.
4137 * @param[in,out] features Features to add to.
4138 *
4139 * @return LY_ERR values.
4140 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004141static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004142parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004143{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004144 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004145 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004146 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004147 enum yang_keyword kw;
4148 struct lysp_feature *feat;
4149
Radek Krejci2c4e7172018-10-19 15:56:26 +02004150 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004151
4152 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004153 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004154 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004155
4156 CHECK_UNIQUENESS(ctx, *features, name, "feature", feat->name);
4157
Radek Krejci6d6556c2018-11-08 09:37:45 +01004158 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004159 switch (kw) {
4160 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004161 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004162 break;
4163 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004164 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004165 break;
4166 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004167 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004168 break;
4169 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004170 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004171 break;
4172 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004173 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004174 break;
4175 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004176 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004177 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004178 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004179 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004180 return ret;
4181}
4182
Michal Vaskoea5abea2018-09-18 13:10:54 +02004183/**
4184 * @brief Parse the identity statement.
4185 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004186 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004187 * @param[in,out] data Data to read from, always moved to currently handled character.
4188 * @param[in,out] identities Identities to add to.
4189 *
4190 * @return LY_ERR values.
4191 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004192static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004193parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004194{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004195 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004196 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004197 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004198 enum yang_keyword kw;
4199 struct lysp_ident *ident;
4200
Radek Krejci2c4e7172018-10-19 15:56:26 +02004201 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004202
4203 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004204 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004205 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004206
4207 CHECK_UNIQUENESS(ctx, *identities, name, "identity", ident->name);
4208
Radek Krejci6d6556c2018-11-08 09:37:45 +01004209 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004210 switch (kw) {
4211 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004212 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004213 break;
4214 case YANG_IF_FEATURE:
Radek Krejci10113652018-11-14 16:56:50 +01004215 YANG_CHECK_STMTVER_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004216 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004217 break;
4218 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004219 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004220 break;
4221 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004222 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004223 break;
4224 case YANG_BASE:
Radek Krejci10113652018-11-14 16:56:50 +01004225 if (ident->bases && ctx->mod->version < 2) {
4226 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
4227 return LY_EVALID;
4228 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004229 LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004230 break;
4231 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004232 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004233 break;
4234 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004235 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004236 return LY_EVALID;
4237 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004238 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004239 return ret;
4240}
4241
Michal Vaskoea5abea2018-09-18 13:10:54 +02004242/**
4243 * @brief Parse the module or submodule statement.
4244 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004245 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004246 * @param[in,out] data Data to read from, always moved to currently handled character.
4247 * @param[in,out] mod Module to write to.
4248 *
4249 * @return LY_ERR values.
4250 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004251static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004252parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004253{
4254 LY_ERR ret = 0;
4255 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004256 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004257 enum yang_keyword kw, prev_kw = 0;
4258 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejcie9e987e2018-10-31 12:50:27 +01004259 struct lysp_module *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004260
4261 /* (sub)module name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004262 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004263 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004264
Radek Krejci6d6556c2018-11-08 09:37:45 +01004265 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004266
Radek Krejcie3846472018-10-15 15:24:51 +02004267#define CHECK_ORDER(SECTION) \
4268 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4269
Michal Vasko7fbc8162018-09-17 10:35:16 +02004270 switch (kw) {
4271 /* module header */
4272 case YANG_NAMESPACE:
4273 case YANG_PREFIX:
4274 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004275 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004276 return LY_EVALID;
4277 }
Radek Krejcie3846472018-10-15 15:24:51 +02004278 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4279 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004280 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004281 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004282 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004283 return LY_EVALID;
4284 }
Radek Krejcie3846472018-10-15 15:24:51 +02004285 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4286 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004287 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004288 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004289 break;
4290 /* linkage */
4291 case YANG_INCLUDE:
4292 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004293 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004294 break;
4295 /* meta */
4296 case YANG_ORGANIZATION:
4297 case YANG_CONTACT:
4298 case YANG_DESCRIPTION:
4299 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004300 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004301 break;
4302
4303 /* revision */
4304 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004305 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004306 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004307 /* body */
4308 case YANG_ANYDATA:
4309 case YANG_ANYXML:
4310 case YANG_AUGMENT:
4311 case YANG_CHOICE:
4312 case YANG_CONTAINER:
4313 case YANG_DEVIATION:
4314 case YANG_EXTENSION:
4315 case YANG_FEATURE:
4316 case YANG_GROUPING:
4317 case YANG_IDENTITY:
4318 case YANG_LEAF:
4319 case YANG_LEAF_LIST:
4320 case YANG_LIST:
4321 case YANG_NOTIFICATION:
4322 case YANG_RPC:
4323 case YANG_TYPEDEF:
4324 case YANG_USES:
4325 case YANG_CUSTOM:
4326 mod_stmt = Y_MOD_BODY;
4327 break;
4328 default:
4329 /* error handled in the next switch */
4330 break;
4331 }
Radek Krejcie3846472018-10-15 15:24:51 +02004332#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004333
Radek Krejcie3846472018-10-15 15:24:51 +02004334 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004335 switch (kw) {
4336 /* module header */
4337 case YANG_YANG_VERSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004338 LY_CHECK_RET(parse_yangversion(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004339 break;
4340 case YANG_NAMESPACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004341 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->ns, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004342 break;
4343 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004344 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts));
Radek Krejci70853c52018-10-15 14:46:16 +02004345 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004346 break;
4347 case YANG_BELONGS_TO:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004348 LY_CHECK_RET(parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004349 break;
4350
4351 /* linkage */
4352 case YANG_INCLUDE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004353 LY_CHECK_RET(parse_include(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004354 break;
4355 case YANG_IMPORT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004356 LY_CHECK_RET(parse_import(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004357 break;
4358
4359 /* meta */
4360 case YANG_ORGANIZATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004361 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->org, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004362 break;
4363 case YANG_CONTACT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004364 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->contact, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004365 break;
4366 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004367 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->dsc, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004368 break;
4369 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004370 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->ref, Y_STR_ARG, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004371 break;
4372
4373 /* revision */
4374 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004375 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004376 break;
4377
4378 /* body */
4379 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01004380 YANG_CHECK_STMTVER_RET(ctx, "anydata", mod->submodule ? "submodule" : "module");
4381 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004382 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004383 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004384 break;
4385 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004386 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004387 break;
4388 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004389 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004390 break;
4391 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004392 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004393 break;
4394 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004395 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004396 break;
4397 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004398 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004399 break;
4400 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004401 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004402 break;
4403
4404 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004405 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004406 break;
4407 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004408 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004409 break;
4410 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004411 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004412 break;
4413 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004414 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004415 break;
4416 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004417 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004418 break;
4419 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004420 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004421 break;
4422 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004423 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004424 break;
4425 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004426 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004427 break;
4428 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004429 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004430 break;
4431 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004432 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004433 break;
4434
4435 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004436 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004437 return LY_EVALID;
4438 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004439 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004440 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004441checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004442 /* mandatory substatements */
4443 if (mod->submodule) {
4444 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004445 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004446 return LY_EVALID;
4447 }
4448 } else {
4449 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004450 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004451 return LY_EVALID;
4452 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004453 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004454 return LY_EVALID;
4455 }
4456 }
4457
Radek Krejcie9e987e2018-10-31 12:50:27 +01004458 /* submodules share the namespace with the module names, so there must not be
4459 * a submodule of the same name in the context, no need for revision matching */
4460 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL);
4461 if (dup && (!mod->submodule || strcmp(dup->belongsto, mod->belongsto))) {
4462 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
4463 mod->submodule ? "submodules" : "module and submodule", mod->name);
4464 return LY_EVALID;
4465 }
4466
Michal Vasko7fbc8162018-09-17 10:35:16 +02004467 return ret;
4468}
4469
Radek Krejcid4557c62018-09-17 11:42:09 +02004470LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01004471yang_parse(struct ly_parser_ctx *context, const char *data, struct lysp_module **mod_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004472{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004473 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004474 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004475 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004476 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004477 struct lysp_module *mod = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004478
4479 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004480 ret = get_keyword(context, &data, &kw, &word, &word_len);
4481 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004482
4483 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004484 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004485 ly_stmt2str(kw));
Radek Krejcibbe09a92018-11-08 09:36:54 +01004486 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004487 }
4488
4489 mod = calloc(1, sizeof *mod);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004490 LY_CHECK_ERR_GOTO(!mod, LOGMEM(context->ctx), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004491 if (kw == YANG_SUBMODULE) {
4492 mod->submodule = 1;
4493 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01004494 mod->parsing = 1;
4495 mod->ctx = context->ctx;
4496 context->mod = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004497
4498 /* substatements */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004499 ret = parse_sub_module(context, &data, mod);
4500 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004501
4502 /* read some trailing spaces or new lines */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004503 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4504 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004505
4506 if (word) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004507 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004508 word_len, word);
4509 free(buf);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004510 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004511 }
4512 assert(!buf);
4513
Radek Krejcibbe09a92018-11-08 09:36:54 +01004514 mod->parsing = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004515 *mod_p = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004516
Radek Krejcibbe09a92018-11-08 09:36:54 +01004517cleanup:
4518 if (ret) {
4519 lysp_module_free(mod);
4520 }
4521
Michal Vasko7fbc8162018-09-17 10:35:16 +02004522 return ret;
4523}