blob: f418f244708e4fd6c9c90f50ce74e2e53b761212 [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 }
2378
2379 return ret;
2380}
2381
Michal Vaskoea5abea2018-09-18 13:10:54 +02002382/**
2383 * @brief Parse the max-elements statement.
2384 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002385 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002386 * @param[in,out] data Data to read from, always moved to currently handled character.
2387 * @param[in,out] max Value to write to.
2388 * @param[in,out] flags Flags to write to.
2389 * @param[in,out] exts Extension instances to add to.
2390 *
2391 * @return LY_ERR values.
2392 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002393static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002394parse_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 +02002395{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002396 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002397 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002398 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002399 unsigned long int num;
2400 enum yang_keyword kw;
2401
2402 if (*flags & LYS_SET_MAX) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002403 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002404 return LY_EVALID;
2405 }
2406 *flags |= LYS_SET_MAX;
2407
2408 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002409 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002410
2411 if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002412 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002413 free(buf);
2414 return LY_EVALID;
2415 }
2416
2417 if (strncmp(word, "unbounded", word_len)) {
2418 errno = 0;
2419 num = strtoul(word, &ptr, 10);
2420 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002421 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002422 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002423 free(buf);
2424 return LY_EVALID;
2425 }
2426 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002427 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002428 free(buf);
2429 return LY_EVALID;
2430 }
2431
2432 *max = num;
2433 }
2434 free(buf);
2435
Radek Krejci6d6556c2018-11-08 09:37:45 +01002436 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002437 switch (kw) {
2438 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002439 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002440 break;
2441 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002442 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002443 return LY_EVALID;
2444 }
2445 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002446 return ret;
2447}
2448
Michal Vaskoea5abea2018-09-18 13:10:54 +02002449/**
2450 * @brief Parse the min-elements statement.
2451 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002452 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002453 * @param[in,out] data Data to read from, always moved to currently handled character.
2454 * @param[in,out] min Value to write to.
2455 * @param[in,out] flags Flags to write to.
2456 * @param[in,out] exts Extension instances to add to.
2457 *
2458 * @return LY_ERR values.
2459 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002460static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002461parse_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 +02002462{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002463 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002464 char *buf, *word, *ptr;
Radek Krejciefd22f62018-09-27 11:47:58 +02002465 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002466 unsigned long int num;
2467 enum yang_keyword kw;
2468
2469 if (*flags & LYS_SET_MIN) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002470 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002471 return LY_EVALID;
2472 }
2473 *flags |= LYS_SET_MIN;
2474
2475 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002476 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002477
2478 if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002479 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002480 free(buf);
2481 return LY_EVALID;
2482 }
2483
2484 errno = 0;
2485 num = strtoul(word, &ptr, 10);
2486 /* we have not parsed the whole argument */
Radek Krejciefd22f62018-09-27 11:47:58 +02002487 if ((size_t)(ptr - word) != word_len) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002488 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002489 free(buf);
2490 return LY_EVALID;
2491 }
2492 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002493 LOGVAL_YANG(ctx, LY_VCODE_OOB, word_len, word, "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002494 free(buf);
2495 return LY_EVALID;
2496 }
2497 *min = num;
2498 free(buf);
2499
Radek Krejci6d6556c2018-11-08 09:37:45 +01002500 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002501 switch (kw) {
2502 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002503 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002504 break;
2505 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002506 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002507 return LY_EVALID;
2508 }
2509 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002510 return ret;
2511}
2512
Michal Vaskoea5abea2018-09-18 13:10:54 +02002513/**
2514 * @brief Parse the ordered-by statement.
2515 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002516 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002517 * @param[in,out] data Data to read from, always moved to currently handled character.
2518 * @param[in,out] flags Flags to write to.
2519 * @param[in,out] exts Extension instances to add to.
2520 *
2521 * @return LY_ERR values.
2522 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002523static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002524parse_orderedby(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002525{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002526 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002527 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002528 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002529 enum yang_keyword kw;
2530
2531 if (*flags & LYS_ORDBY_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002532 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002533 return LY_EVALID;
2534 }
2535
2536 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002537 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002538
2539 if ((word_len == 6) && !strncmp(word, "system", word_len)) {
2540 *flags |= LYS_ORDBY_SYSTEM;
2541 } else if ((word_len == 4) && !strncmp(word, "user", word_len)) {
2542 *flags |= LYS_ORDBY_USER;
2543 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002544 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002545 free(buf);
2546 return LY_EVALID;
2547 }
2548 free(buf);
2549
Radek Krejci6d6556c2018-11-08 09:37:45 +01002550 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002551 switch (kw) {
2552 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002553 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002554 break;
2555 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002556 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002557 return LY_EVALID;
2558 }
2559 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002560 return ret;
2561}
2562
Michal Vaskoea5abea2018-09-18 13:10:54 +02002563/**
2564 * @brief Parse the leaf-list statement.
2565 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002566 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002567 * @param[in,out] data Data to read from, always moved to currently handled character.
2568 * @param[in,out] siblings Siblings to add to.
2569 *
2570 * @return LY_ERR values.
2571 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002572static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002573parse_leaflist(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002574{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002575 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002576 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002577 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002578 enum yang_keyword kw;
2579 struct lysp_node *iter;
2580 struct lysp_node_leaflist *llist;
2581
2582 /* create structure */
2583 llist = calloc(1, sizeof *llist);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002584 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002585 llist->nodetype = LYS_LEAFLIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002586 llist->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002587
2588 /* insert into siblings */
2589 if (!*siblings) {
2590 *siblings = (struct lysp_node *)llist;
2591 } else {
2592 for (iter = *siblings; iter->next; iter = iter->next);
2593 iter->next = (struct lysp_node *)llist;
2594 }
2595
2596 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002597 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002598 INSERT_WORD(ctx, buf, llist->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002599
2600 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002601 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002602 switch (kw) {
2603 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002604 LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002605 break;
2606 case YANG_DEFAULT:
Radek Krejci10113652018-11-14 16:56:50 +01002607 YANG_CHECK_STMTVER_RET(ctx, "default", "leaf-list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002608 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 +02002609 break;
2610 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002611 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 +02002612 break;
2613 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002614 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 +02002615 break;
2616 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002617 LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002618 break;
2619 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002620 LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002621 break;
2622 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002623 LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002624 break;
2625 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002626 LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002627 break;
2628 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002629 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 +02002630 break;
2631 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002632 LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002633 break;
2634 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002635 LY_CHECK_RET(parse_type(ctx, data, &llist->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002636 break;
2637 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002638 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 +02002639 break;
2640 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002641 LY_CHECK_RET(parse_when(ctx, data, &llist->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002642 break;
2643 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002644 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002645 break;
2646 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002647 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002648 return LY_EVALID;
2649 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002650 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002651 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01002652checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002653 /* mandatory substatements */
2654 if (!llist->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002655 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "leaf-list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002656 return LY_EVALID;
2657 }
2658
2659 return ret;
2660}
2661
Michal Vaskoea5abea2018-09-18 13:10:54 +02002662/**
2663 * @brief Parse the refine statement.
2664 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002665 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002666 * @param[in,out] data Data to read from, always moved to currently handled character.
2667 * @param[in,out] refines Refines to add to.
2668 *
2669 * @return LY_ERR values.
2670 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002671static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02002672parse_refine(struct ly_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002673{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002674 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002675 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002676 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002677 enum yang_keyword kw;
2678 struct lysp_refine *rf;
2679
Radek Krejci2c4e7172018-10-19 15:56:26 +02002680 LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002681
2682 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002683 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002684 INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002685
Radek Krejci6d6556c2018-11-08 09:37:45 +01002686 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002687 switch (kw) {
2688 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002689 LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002690 break;
2691 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002692 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 +02002693 break;
2694 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002695 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 +02002696 break;
2697 case YANG_IF_FEATURE:
Radek Krejci10113652018-11-14 16:56:50 +01002698 YANG_CHECK_STMTVER_RET(ctx, "if-feature", "refine");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002699 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 +02002700 break;
2701 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002702 LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002703 break;
2704 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002705 LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002706 break;
2707 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002708 LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002709 break;
2710 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002711 LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002712 break;
2713 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002714 LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002715 break;
2716 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002717 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 +02002718 break;
2719 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002720 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002721 break;
2722 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002723 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002724 return LY_EVALID;
2725 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002726 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002727 return ret;
2728}
2729
Michal Vaskoea5abea2018-09-18 13:10:54 +02002730/**
2731 * @brief Parse the typedef statement.
2732 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002733 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002734 * @param[in,out] data Data to read from, always moved to currently handled character.
2735 * @param[in,out] typedefs Typedefs to add to.
2736 *
2737 * @return LY_ERR values.
2738 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002739static LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01002740parse_typedef(struct ly_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002741{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002742 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002743 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002744 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002745 enum yang_keyword kw;
2746 struct lysp_tpdf *tpdf;
2747
Radek Krejci2c4e7172018-10-19 15:56:26 +02002748 LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002749
2750 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002751 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002752 INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002753
2754 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002755 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002756 switch (kw) {
2757 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002758 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 +02002759 break;
2760 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002761 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 +02002762 break;
2763 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002764 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 +02002765 break;
2766 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002767 LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002768 break;
2769 case YANG_TYPE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002770 LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002771 break;
2772 case YANG_UNITS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002773 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 +02002774 break;
2775 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002776 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002777 break;
2778 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002779 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002780 return LY_EVALID;
2781 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002782 }
Radek Krejcic59bc972018-09-17 16:13:06 +02002783 LY_CHECK_RET(ret);
Radek Krejcibbe09a92018-11-08 09:36:54 +01002784checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02002785 /* mandatory substatements */
2786 if (!tpdf->type.name) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02002787 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "type", "typedef");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002788 return LY_EVALID;
2789 }
2790
Radek Krejcibbe09a92018-11-08 09:36:54 +01002791 /* store data for collision check */
2792 if (parent) {
2793 ly_set_add(&ctx->tpdfs_nodes, parent, 0);
2794 }
2795
Michal Vasko7fbc8162018-09-17 10:35:16 +02002796 return ret;
2797}
2798
Michal Vaskoea5abea2018-09-18 13:10:54 +02002799/**
2800 * @brief Parse the input or output statement.
2801 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002802 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002803 * @param[in,out] data Data to read from, always moved to currently handled character.
2804 * @param[in] kw Type of this particular keyword
2805 * @param[in,out] inout_p Input/output pointer to write to.
2806 *
2807 * @return LY_ERR values.
2808 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002809static LY_ERR
Radek Krejci10113652018-11-14 16:56:50 +01002810parse_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 +02002811{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002812 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002813 char *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002814 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002815 struct lysp_action_inout *inout;
Radek Krejci10113652018-11-14 16:56:50 +01002816 enum yang_keyword kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002817
2818 if (*inout_p) {
Radek Krejci10113652018-11-14 16:56:50 +01002819 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002820 return LY_EVALID;
2821 }
2822
2823 /* create structure */
2824 inout = calloc(1, sizeof *inout);
Radek Krejci44ceedc2018-10-02 15:54:31 +02002825 LY_CHECK_ERR_RET(!inout, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002826 *inout_p = inout;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002827 inout->nodetype = LYS_INOUT;
2828 inout->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002829
2830 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01002831 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002832 switch (kw) {
2833 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01002834 YANG_CHECK_STMTVER_RET(ctx, "anydata", ly_stmt2str(inout_kw));
2835 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002836 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002837 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002838 break;
2839 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002840 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002841 break;
2842 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002843 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002844 break;
2845 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002846 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002847 break;
2848 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002849 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002850 break;
2851 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002852 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002853 break;
2854 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002855 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout, &inout->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002856 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002857 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002858 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout, data, &inout->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002859 break;
2860 case YANG_MUST:
Radek Krejci10113652018-11-14 16:56:50 +01002861 YANG_CHECK_STMTVER_RET(ctx, "must", ly_stmt2str(inout_kw));
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002862 LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002863 break;
2864 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002865 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout, &inout->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002866 break;
2867 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002868 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002869 break;
2870 default:
Radek Krejci10113652018-11-14 16:56:50 +01002871 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002872 return LY_EVALID;
2873 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002874 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002875 return ret;
2876}
2877
Michal Vaskoea5abea2018-09-18 13:10:54 +02002878/**
2879 * @brief Parse the action statement.
2880 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002881 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002882 * @param[in,out] data Data to read from, always moved to currently handled character.
2883 * @param[in,out] actions Actions to add to.
2884 *
2885 * @return LY_ERR values.
2886 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002887static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002888parse_action(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002889{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002890 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002891 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002892 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002893 enum yang_keyword kw;
2894 struct lysp_action *act;
2895
Radek Krejci2c4e7172018-10-19 15:56:26 +02002896 LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002897
2898 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002899 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002900 INSERT_WORD(ctx, buf, act->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002901 act->nodetype = LYS_ACTION;
2902 act->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002903
Radek Krejci6d6556c2018-11-08 09:37:45 +01002904 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002905 switch (kw) {
2906 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002907 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 +02002908 break;
2909 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002910 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 +02002911 break;
2912 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002913 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 +02002914 break;
2915 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002916 LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002917 break;
2918
2919 case YANG_INPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002920 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002921 break;
2922 case YANG_OUTPUT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002923 LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002924 break;
2925
2926 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01002927 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002928 break;
2929 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002930 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002931 break;
2932 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002933 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002934 break;
2935 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02002936 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
Michal Vasko7fbc8162018-09-17 10:35:16 +02002937 return LY_EVALID;
2938 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002939 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02002940 return ret;
2941}
2942
Michal Vaskoea5abea2018-09-18 13:10:54 +02002943/**
2944 * @brief Parse the notification statement.
2945 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02002946 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02002947 * @param[in,out] data Data to read from, always moved to currently handled character.
2948 * @param[in,out] notifs Notifications to add to.
2949 *
2950 * @return LY_ERR values.
2951 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002952static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002953parse_notif(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
Michal Vasko7fbc8162018-09-17 10:35:16 +02002954{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002955 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002956 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02002957 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002958 enum yang_keyword kw;
2959 struct lysp_notif *notif;
2960
Radek Krejci2c4e7172018-10-19 15:56:26 +02002961 LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02002962
2963 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002964 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02002965 INSERT_WORD(ctx, buf, notif->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002966 notif->nodetype = LYS_NOTIF;
2967 notif->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02002968
Radek Krejci6d6556c2018-11-08 09:37:45 +01002969 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02002970 switch (kw) {
2971 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002972 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 +02002973 break;
2974 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002975 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 +02002976 break;
2977 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002978 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 +02002979 break;
2980 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002981 LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002982 break;
2983
2984 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01002985 YANG_CHECK_STMTVER_RET(ctx, "anydata", "notification");
2986 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02002987 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002988 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002989 break;
2990 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002991 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002992 break;
2993 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002994 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002995 break;
2996 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01002997 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02002998 break;
2999 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003000 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003001 break;
3002 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003003 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003004 break;
3005 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003006 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003007 break;
3008
3009 case YANG_MUST:
Radek Krejci10113652018-11-14 16:56:50 +01003010 YANG_CHECK_STMTVER_RET(ctx, "must", "notification");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003011 LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003012 break;
3013 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003014 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003015 break;
3016 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003017 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003018 break;
3019 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003020 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003021 break;
3022 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003023 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003024 return LY_EVALID;
3025 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003026 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003027 return ret;
3028}
3029
Michal Vaskoea5abea2018-09-18 13:10:54 +02003030/**
3031 * @brief Parse the grouping statement.
3032 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003033 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003034 * @param[in,out] data Data to read from, always moved to currently handled character.
3035 * @param[in,out] groupings Groupings to add to.
3036 *
3037 * @return LY_ERR values.
3038 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003039static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003040parse_grouping(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003041{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003042 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003043 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003044 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003045 enum yang_keyword kw;
3046 struct lysp_grp *grp;
3047
Radek Krejci2c4e7172018-10-19 15:56:26 +02003048 LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003049
3050 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003051 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003052 INSERT_WORD(ctx, buf, grp->name, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003053 grp->nodetype = LYS_GROUPING;
3054 grp->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003055
Radek Krejci6d6556c2018-11-08 09:37:45 +01003056 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003057 switch (kw) {
3058 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003059 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 +02003060 break;
3061 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003062 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 +02003063 break;
3064 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003065 LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003066 break;
3067
3068 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003069 YANG_CHECK_STMTVER_RET(ctx, "anydata", "grouping");
3070 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003071 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003072 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003073 break;
3074 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003075 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003076 break;
3077 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003078 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003079 break;
3080 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003081 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003082 break;
3083 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003084 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003085 break;
3086 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003087 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003088 break;
3089 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003090 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003091 break;
3092
3093 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003094 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003095 break;
3096 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003097 YANG_CHECK_STMTVER_RET(ctx, "action", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003098 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003099 break;
3100 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003101 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003102 break;
3103 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003104 YANG_CHECK_STMTVER_RET(ctx, "notification", "grouping");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003105 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003106 break;
3107 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003108 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003109 break;
3110 default:
Radek Krejci10113652018-11-14 16:56:50 +01003111 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003112 return LY_EVALID;
3113 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003114 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003115 return ret;
3116}
3117
Michal Vaskoea5abea2018-09-18 13:10:54 +02003118/**
3119 * @brief Parse the refine statement.
3120 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003121 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003122 * @param[in,out] data Data to read from, always moved to currently handled character.
3123 * @param[in,out] augments Augments to add to.
3124 *
3125 * @return LY_ERR values.
3126 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003127static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003128parse_augment(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003129{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003130 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003131 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003132 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003133 enum yang_keyword kw;
3134 struct lysp_augment *aug;
3135
Radek Krejci2c4e7172018-10-19 15:56:26 +02003136 LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003137
3138 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003139 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003140 INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003141 aug->nodetype = LYS_AUGMENT;
3142 aug->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003143
Radek Krejci6d6556c2018-11-08 09:37:45 +01003144 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003145 switch (kw) {
3146 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003147 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 +02003148 break;
3149 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003150 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 +02003151 break;
3152 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003153 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 +02003154 break;
3155 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003156 LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003157 break;
3158 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003159 LY_CHECK_RET(parse_when(ctx, data, &aug->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003160 break;
3161
3162 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003163 YANG_CHECK_STMTVER_RET(ctx, "anydata", "augment");
3164 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003165 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003166 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003167 break;
3168 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003169 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003170 break;
3171 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003172 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003173 break;
3174 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003175 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003176 break;
3177 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003178 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003179 break;
3180 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003181 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003182 break;
3183 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003184 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003185 break;
3186 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003187 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003188 break;
3189
3190 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003191 YANG_CHECK_STMTVER_RET(ctx, "action", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003192 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003193 break;
3194 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003195 YANG_CHECK_STMTVER_RET(ctx, "notification", "augment");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003196 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003197 break;
3198 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003199 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003200 break;
3201 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003202 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003203 return LY_EVALID;
3204 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003205 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003206 return ret;
3207}
3208
Michal Vaskoea5abea2018-09-18 13:10:54 +02003209/**
3210 * @brief Parse the uses statement.
3211 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003212 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003213 * @param[in,out] data Data to read from, always moved to currently handled character.
3214 * @param[in,out] siblings Siblings to add to.
3215 *
3216 * @return LY_ERR values.
3217 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003218static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003219parse_uses(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003220{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003221 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003222 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003223 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003224 enum yang_keyword kw;
3225 struct lysp_node *iter;
3226 struct lysp_node_uses *uses;
3227
3228 /* create structure */
3229 uses = calloc(1, sizeof *uses);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003230 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003231 uses->nodetype = LYS_USES;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003232 uses->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003233
3234 /* insert into siblings */
3235 if (!*siblings) {
3236 *siblings = (struct lysp_node *)uses;
3237 } else {
3238 for (iter = *siblings; iter->next; iter = iter->next);
3239 iter->next = (struct lysp_node *)uses;
3240 }
3241
3242 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003243 LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003244 INSERT_WORD(ctx, buf, uses->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003245
3246 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003247 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003248 switch (kw) {
3249 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003250 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 +02003251 break;
3252 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003253 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 +02003254 break;
3255 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003256 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 +02003257 break;
3258 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003259 LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003260 break;
3261 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003262 LY_CHECK_RET(parse_when(ctx, data, &uses->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003263 break;
3264
3265 case YANG_REFINE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003266 LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003267 break;
3268 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003269 LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003270 break;
3271 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003272 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003273 break;
3274 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003275 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003276 return LY_EVALID;
3277 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003278 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003279 return ret;
3280}
3281
Michal Vaskoea5abea2018-09-18 13:10:54 +02003282/**
3283 * @brief Parse the case statement.
3284 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003285 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003286 * @param[in,out] data Data to read from, always moved to currently handled character.
3287 * @param[in,out] siblings Siblings to add to.
3288 *
3289 * @return LY_ERR values.
3290 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003291static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003292parse_case(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003293{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003294 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003295 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003296 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003297 enum yang_keyword kw;
3298 struct lysp_node *iter;
3299 struct lysp_node_case *cas;
3300
3301 /* create structure */
3302 cas = calloc(1, sizeof *cas);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003303 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003304 cas->nodetype = LYS_CASE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003305 cas->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003306
3307 /* insert into siblings */
3308 if (!*siblings) {
3309 *siblings = (struct lysp_node *)cas;
3310 } else {
3311 for (iter = *siblings; iter->next; iter = iter->next);
3312 iter->next = (struct lysp_node *)cas;
3313 }
3314
3315 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003316 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003317 INSERT_WORD(ctx, buf, cas->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003318
3319 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003320 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003321 switch (kw) {
3322 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003323 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 +02003324 break;
3325 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003326 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 +02003327 break;
3328 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003329 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 +02003330 break;
3331 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003332 LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003333 break;
3334 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003335 LY_CHECK_RET(parse_when(ctx, data, &cas->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003336 break;
3337
3338 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003339 YANG_CHECK_STMTVER_RET(ctx, "anydata", "case");
3340 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003341 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003342 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003343 break;
3344 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003345 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003346 break;
3347 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003348 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003349 break;
3350 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003351 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003352 break;
3353 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003354 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003355 break;
3356 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003357 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003358 break;
3359 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003360 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003361 break;
3362 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003363 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003364 break;
3365 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003366 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003367 return LY_EVALID;
3368 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003369 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003370 return ret;
3371}
3372
Michal Vaskoea5abea2018-09-18 13:10:54 +02003373/**
3374 * @brief Parse the choice statement.
3375 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003376 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003377 * @param[in,out] data Data to read from, always moved to currently handled character.
3378 * @param[in,out] siblings Siblings to add to.
3379 *
3380 * @return LY_ERR values.
3381 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003382static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003383parse_choice(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003384{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003385 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003386 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003387 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003388 enum yang_keyword kw;
3389 struct lysp_node *iter;
Radek Krejci44ceedc2018-10-02 15:54:31 +02003390 struct lysp_node_choice *choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003391
3392 /* create structure */
Radek Krejci44ceedc2018-10-02 15:54:31 +02003393 choice = calloc(1, sizeof *choice);
3394 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->ctx), LY_EMEM);
3395 choice->nodetype = LYS_CHOICE;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003396 choice->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003397
3398 /* insert into siblings */
3399 if (!*siblings) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003400 *siblings = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003401 } else {
3402 for (iter = *siblings; iter->next; iter = iter->next);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003403 iter->next = (struct lysp_node *)choice;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003404 }
3405
3406 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003407 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003408 INSERT_WORD(ctx, buf, choice->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003409
3410 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003411 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003412 switch (kw) {
3413 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003414 LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003415 break;
3416 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003417 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 +02003418 break;
3419 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003420 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 +02003421 break;
3422 case YANG_MANDATORY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003423 LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003424 break;
3425 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003426 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 +02003427 break;
3428 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003429 LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003430 break;
3431 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003432 LY_CHECK_RET(parse_when(ctx, data, &choice->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003433 break;
3434 case YANG_DEFAULT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003435 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 +02003436 break;
3437
3438 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003439 YANG_CHECK_STMTVER_RET(ctx, "anydata", "choice");
3440 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003441 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003442 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003443 break;
3444 case YANG_CASE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003445 LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003446 break;
3447 case YANG_CHOICE:
Radek Krejci10113652018-11-14 16:56:50 +01003448 YANG_CHECK_STMTVER_RET(ctx, "choice", "choice");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003449 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003450 break;
3451 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003452 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003453 break;
3454 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003455 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003456 break;
3457 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003458 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003459 break;
3460 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003461 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003462 break;
3463 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003464 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003465 break;
3466 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003467 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003468 return LY_EVALID;
3469 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003470 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003471 return ret;
3472}
3473
Michal Vaskoea5abea2018-09-18 13:10:54 +02003474/**
3475 * @brief Parse the container statement.
3476 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003477 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003478 * @param[in,out] data Data to read from, always moved to currently handled character.
3479 * @param[in,out] siblings Siblings to add to.
3480 *
3481 * @return LY_ERR values.
3482 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003483static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003484parse_container(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003485{
3486 LY_ERR ret = 0;
3487 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003488 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003489 enum yang_keyword kw;
3490 struct lysp_node *iter;
3491 struct lysp_node_container *cont;
3492
3493 /* create structure */
3494 cont = calloc(1, sizeof *cont);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003495 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003496 cont->nodetype = LYS_CONTAINER;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003497 cont->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003498
3499 /* insert into siblings */
3500 if (!*siblings) {
3501 *siblings = (struct lysp_node *)cont;
3502 } else {
3503 for (iter = *siblings; iter->next; iter = iter->next);
3504 iter->next = (struct lysp_node *)cont;
3505 }
3506
3507 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003508 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003509 INSERT_WORD(ctx, buf, cont->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003510
3511 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003512 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003513 switch (kw) {
3514 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003515 LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003516 break;
3517 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003518 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 +02003519 break;
3520 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003521 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 +02003522 break;
3523 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003524 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 +02003525 break;
3526 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003527 LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003528 break;
3529 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003530 LY_CHECK_RET(parse_when(ctx, data, &cont->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003531 break;
3532 case YANG_PRESENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003533 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 +02003534 break;
3535
3536 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003537 YANG_CHECK_STMTVER_RET(ctx, "anydata", "container");
3538 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003539 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003540 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003541 break;
3542 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003543 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003544 break;
3545 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003546 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003547 break;
3548 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003549 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003550 break;
3551 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003552 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003553 break;
3554 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003555 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003556 break;
3557 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003558 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003559 break;
3560
3561 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003562 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003563 break;
3564 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003565 LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003566 break;
3567 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003568 YANG_CHECK_STMTVER_RET(ctx, "action", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003569 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003570 break;
3571 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003572 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003573 break;
3574 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003575 YANG_CHECK_STMTVER_RET(ctx, "notification", "container");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003576 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003577 break;
3578 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003579 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003580 break;
3581 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003582 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003583 return LY_EVALID;
3584 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003585 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003586 return ret;
3587}
3588
Michal Vaskoea5abea2018-09-18 13:10:54 +02003589/**
3590 * @brief Parse the list statement.
3591 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003592 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003593 * @param[in,out] data Data to read from, always moved to currently handled character.
3594 * @param[in,out] siblings Siblings to add to.
3595 *
3596 * @return LY_ERR values.
3597 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003598static LY_ERR
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003599parse_list(struct ly_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003600{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003601 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003602 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003603 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003604 enum yang_keyword kw;
3605 struct lysp_node *iter;
3606 struct lysp_node_list *list;
3607
3608 /* create structure */
3609 list = calloc(1, sizeof *list);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003610 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003611 list->nodetype = LYS_LIST;
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003612 list->parent = parent;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003613
3614 /* insert into siblings */
3615 if (!*siblings) {
3616 *siblings = (struct lysp_node *)list;
3617 } else {
3618 for (iter = *siblings; iter->next; iter = iter->next);
3619 iter->next = (struct lysp_node *)list;
3620 }
3621
3622 /* get name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003623 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003624 INSERT_WORD(ctx, buf, list->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003625
3626 /* parse substatements */
Radek Krejci6d6556c2018-11-08 09:37:45 +01003627 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003628 switch (kw) {
3629 case YANG_CONFIG:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003630 LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003631 break;
3632 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003633 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 +02003634 break;
3635 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003636 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 +02003637 break;
3638 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003639 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 +02003640 break;
3641 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003642 LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003643 break;
3644 case YANG_WHEN:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003645 LY_CHECK_RET(parse_when(ctx, data, &list->when));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003646 break;
3647 case YANG_KEY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003648 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 +02003649 break;
3650 case YANG_MAX_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003651 LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003652 break;
3653 case YANG_MIN_ELEMENTS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003654 LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003655 break;
3656 case YANG_ORDERED_BY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003657 LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003658 break;
3659 case YANG_UNIQUE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003660 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 +02003661 break;
3662
3663 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01003664 YANG_CHECK_STMTVER_RET(ctx, "anydata", "list");
3665 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003666 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003667 LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003668 break;
3669 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003670 LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003671 break;
3672 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003673 LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003674 break;
3675 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003676 LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003677 break;
3678 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003679 LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003680 break;
3681 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003682 LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003683 break;
3684 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003685 LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003686 break;
3687
3688 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01003689 LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003690 break;
3691 case YANG_MUST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003692 LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003693 break;
3694 case YANG_ACTION:
Radek Krejci10113652018-11-14 16:56:50 +01003695 YANG_CHECK_STMTVER_RET(ctx, "action", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003696 LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003697 break;
3698 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003699 LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003700 break;
3701 case YANG_NOTIFICATION:
Radek Krejci10113652018-11-14 16:56:50 +01003702 YANG_CHECK_STMTVER_RET(ctx, "notification", "list");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003703 LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003704 break;
3705 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003706 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003707 break;
3708 default:
Radek Krejci10113652018-11-14 16:56:50 +01003709 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003710 return LY_EVALID;
3711 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003712 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003713
3714 return ret;
3715}
3716
Michal Vaskoea5abea2018-09-18 13:10:54 +02003717/**
3718 * @brief Parse the yin-element statement.
3719 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003720 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003721 * @param[in,out] data Data to read from, always moved to currently handled character.
3722 * @param[in,out] flags Flags to write to.
3723 * @param[in,out] exts Extension instances to add to.
3724 *
3725 * @return LY_ERR values.
3726 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003727static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003728parse_yinelement(struct ly_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003729{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003730 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003731 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003732 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003733 enum yang_keyword kw;
3734
3735 if (*flags & LYS_YINELEM_MASK) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003736 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003737 return LY_EVALID;
3738 }
3739
3740 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003741 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003742
3743 if ((word_len == 4) && !strncmp(word, "true", word_len)) {
3744 *flags |= LYS_YINELEM_TRUE;
3745 } else if ((word_len == 5) && !strncmp(word, "false", word_len)) {
3746 *flags |= LYS_YINELEM_FALSE;
3747 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003748 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003749 free(buf);
3750 return LY_EVALID;
3751 }
3752 free(buf);
3753
Radek Krejci6d6556c2018-11-08 09:37:45 +01003754 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003755 switch (kw) {
3756 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003757 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
3758 LY_CHECK_RET(ret); break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003759 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003760 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003761 return LY_EVALID;
3762 }
3763 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003764 return ret;
3765}
3766
Michal Vaskoea5abea2018-09-18 13:10:54 +02003767/**
3768 * @brief Parse the yin-element statement.
3769 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003770 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003771 * @param[in,out] data Data to read from, always moved to currently handled character.
3772 * @param[in,out] argument Value to write to.
3773 * @param[in,out] flags Flags to write to.
3774 * @param[in,out] exts Extension instances to add to.
3775 *
3776 * @return LY_ERR values.
3777 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003778static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003779parse_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 +02003780{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003781 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003782 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003783 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003784 enum yang_keyword kw;
3785
3786 if (*argument) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003787 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003788 return LY_EVALID;
3789 }
3790
3791 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003792 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003793 INSERT_WORD(ctx, buf, *argument, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003794
Radek Krejci6d6556c2018-11-08 09:37:45 +01003795 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003796 switch (kw) {
3797 case YANG_YIN_ELEMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003798 LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003799 break;
3800 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003801 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003802 break;
3803 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003804 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003805 return LY_EVALID;
3806 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003807 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003808 return ret;
3809}
3810
Michal Vaskoea5abea2018-09-18 13:10:54 +02003811/**
3812 * @brief Parse the extension statement.
3813 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003814 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003815 * @param[in,out] data Data to read from, always moved to currently handled character.
3816 * @param[in,out] extensions Extensions to add to.
3817 *
3818 * @return LY_ERR values.
3819 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003820static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003821parse_extension(struct ly_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003822{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003823 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003824 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003825 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003826 enum yang_keyword kw;
3827 struct lysp_ext *ex;
3828
Radek Krejci2c4e7172018-10-19 15:56:26 +02003829 LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003830
3831 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003832 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02003833 INSERT_WORD(ctx, buf, ex->name, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003834
Radek Krejci6d6556c2018-11-08 09:37:45 +01003835 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003836 switch (kw) {
3837 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003838 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 +02003839 break;
3840 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003841 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 +02003842 break;
3843 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003844 LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003845 break;
3846 case YANG_ARGUMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003847 LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003848 break;
3849 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003850 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003851 break;
3852 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003853 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003854 return LY_EVALID;
3855 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003856 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02003857 return ret;
3858}
3859
Michal Vaskoea5abea2018-09-18 13:10:54 +02003860/**
3861 * @brief Parse the deviate statement.
3862 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02003863 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02003864 * @param[in,out] data Data to read from, always moved to currently handled character.
3865 * @param[in,out] deviates Deviates to add to.
3866 *
3867 * @return LY_ERR values.
3868 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02003869static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02003870parse_deviate(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
Michal Vasko7fbc8162018-09-17 10:35:16 +02003871{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003872 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003873 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02003874 size_t word_len, dev_mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003875 enum yang_keyword kw;
3876 struct lysp_deviate *iter, *d;
3877 struct lysp_deviate_add *d_add = NULL;
3878 struct lysp_deviate_rpl *d_rpl = NULL;
3879 struct lysp_deviate_del *d_del = NULL;
3880 const char **d_units, ***d_uniques, ***d_dflts;
3881 struct lysp_restr **d_musts;
3882 uint16_t *d_flags;
3883 uint32_t *d_min, *d_max;
3884
3885 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003886 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003887
3888 if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
3889 dev_mod = LYS_DEV_NOT_SUPPORTED;
3890 } else if ((word_len == 3) && !strncmp(word, "add", word_len)) {
3891 dev_mod = LYS_DEV_ADD;
3892 } else if ((word_len == 7) && !strncmp(word, "replace", word_len)) {
3893 dev_mod = LYS_DEV_REPLACE;
3894 } else if ((word_len == 6) && !strncmp(word, "delete", word_len)) {
3895 dev_mod = LYS_DEV_DELETE;
3896 } else {
Radek Krejci44ceedc2018-10-02 15:54:31 +02003897 LOGVAL_YANG(ctx, LY_VCODE_INVAL, word_len, word, "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02003898 free(buf);
3899 return LY_EVALID;
3900 }
3901 free(buf);
3902
3903 /* create structure */
3904 switch (dev_mod) {
3905 case LYS_DEV_NOT_SUPPORTED:
3906 d = calloc(1, sizeof *d);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003907 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003908 break;
3909 case LYS_DEV_ADD:
3910 d_add = calloc(1, sizeof *d_add);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003911 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003912 d = (struct lysp_deviate *)d_add;
3913 d_units = &d_add->units;
3914 d_uniques = &d_add->uniques;
3915 d_dflts = &d_add->dflts;
3916 d_musts = &d_add->musts;
3917 d_flags = &d_add->flags;
3918 d_min = &d_add->min;
3919 d_max = &d_add->max;
3920 break;
3921 case LYS_DEV_REPLACE:
3922 d_rpl = calloc(1, sizeof *d_rpl);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003923 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003924 d = (struct lysp_deviate *)d_rpl;
3925 d_units = &d_rpl->units;
3926 d_flags = &d_rpl->flags;
3927 d_min = &d_rpl->min;
3928 d_max = &d_rpl->max;
3929 break;
3930 case LYS_DEV_DELETE:
3931 d_del = calloc(1, sizeof *d_del);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003932 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003933 d = (struct lysp_deviate *)d_del;
3934 d_units = &d_del->units;
3935 d_uniques = &d_del->uniques;
3936 d_dflts = &d_del->dflts;
3937 d_musts = &d_del->musts;
3938 d_flags = &d_del->flags;
Michal Vasko7fbc8162018-09-17 10:35:16 +02003939 break;
3940 default:
3941 assert(0);
Radek Krejci44ceedc2018-10-02 15:54:31 +02003942 LOGINT_RET(ctx->ctx);
Michal Vasko7fbc8162018-09-17 10:35:16 +02003943 }
3944 d->mod = dev_mod;
3945
3946 /* insert into siblings */
3947 if (!*deviates) {
3948 *deviates = d;
3949 } else {
3950 for (iter = *deviates; iter->next; iter = iter->next);
3951 iter->next = d;
3952 }
3953
Radek Krejci6d6556c2018-11-08 09:37:45 +01003954 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02003955 switch (kw) {
3956 case YANG_CONFIG:
3957 switch (dev_mod) {
3958 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003959 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003960 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003961 return LY_EVALID;
3962 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003963 LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003964 break;
3965 }
3966 break;
3967 case YANG_DEFAULT:
3968 switch (dev_mod) {
3969 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003970 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003971 return LY_EVALID;
3972 case LYS_DEV_REPLACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003973 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 +02003974 break;
3975 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003976 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 +02003977 break;
3978 }
3979 break;
3980 case YANG_MANDATORY:
3981 switch (dev_mod) {
3982 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003983 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003984 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003985 return LY_EVALID;
3986 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003987 LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003988 break;
3989 }
3990 break;
3991 case YANG_MAX_ELEMENTS:
3992 switch (dev_mod) {
3993 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02003994 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02003995 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003996 return LY_EVALID;
3997 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01003998 LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02003999 break;
4000 }
4001 break;
4002 case YANG_MIN_ELEMENTS:
4003 switch (dev_mod) {
4004 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004005 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004006 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004007 return LY_EVALID;
4008 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004009 LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004010 break;
4011 }
4012 break;
4013 case YANG_MUST:
4014 switch (dev_mod) {
4015 case LYS_DEV_NOT_SUPPORTED:
Michal Vasko492bec72018-09-18 13:11:10 +02004016 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004017 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004018 return LY_EVALID;
4019 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004020 LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004021 break;
4022 }
4023 break;
4024 case YANG_TYPE:
4025 switch (dev_mod) {
4026 case LYS_DEV_NOT_SUPPORTED:
4027 case LYS_DEV_ADD:
4028 case LYS_DEV_DELETE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004029 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004030 return LY_EVALID;
4031 default:
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004032 if (d_rpl->type) {
4033 LOGVAL_YANG(ctx, LY_VCODE_DUPSTMT, ly_stmt2str(kw));
4034 return LY_EVALID;
4035 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004036 d_rpl->type = calloc(1, sizeof *d_rpl->type);
Radek Krejci44ceedc2018-10-02 15:54:31 +02004037 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004038 LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004039 break;
4040 }
4041 break;
4042 case YANG_UNIQUE:
4043 switch (dev_mod) {
4044 case LYS_DEV_NOT_SUPPORTED:
4045 case LYS_DEV_REPLACE:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004046 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004047 return LY_EVALID;
4048 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004049 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 +02004050 break;
4051 }
4052 break;
4053 case YANG_UNITS:
4054 switch (dev_mod) {
4055 case LYS_DEV_NOT_SUPPORTED:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004056 LOGVAL_YANG(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004057 return LY_EVALID;
4058 default:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004059 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 +02004060 break;
4061 }
4062 break;
4063 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004064 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004065 break;
4066 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004067 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004068 return LY_EVALID;
4069 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004070 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004071 return ret;
4072}
4073
Michal Vaskoea5abea2018-09-18 13:10:54 +02004074/**
4075 * @brief Parse the deviation statement.
4076 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004077 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004078 * @param[in,out] data Data to read from, always moved to currently handled character.
4079 * @param[in,out] deviations Deviations to add to.
4080 *
4081 * @return LY_ERR values.
4082 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004083static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004084parse_deviation(struct ly_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004085{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004086 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004087 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004088 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004089 enum yang_keyword kw;
4090 struct lysp_deviation *dev;
4091
Radek Krejci2c4e7172018-10-19 15:56:26 +02004092 LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004093
4094 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004095 LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004096 INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004097
Radek Krejci6d6556c2018-11-08 09:37:45 +01004098 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004099 switch (kw) {
4100 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004101 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 +02004102 break;
4103 case YANG_DEVIATE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004104 LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004105 break;
4106 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004107 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 +02004108 break;
4109 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004110 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004111 break;
4112 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004113 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004114 return LY_EVALID;
4115 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004116 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004117 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004118checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004119 /* mandatory substatements */
4120 if (!dev->deviates) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004121 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "deviate", "deviation");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004122 return LY_EVALID;
4123 }
4124
4125 return ret;
4126}
4127
Michal Vaskoea5abea2018-09-18 13:10:54 +02004128/**
4129 * @brief Parse the feature statement.
4130 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004131 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004132 * @param[in,out] data Data to read from, always moved to currently handled character.
4133 * @param[in,out] features Features to add to.
4134 *
4135 * @return LY_ERR values.
4136 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004137static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004138parse_feature(struct ly_parser_ctx *ctx, const char **data, struct lysp_feature **features)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004139{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004140 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004141 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004142 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004143 enum yang_keyword kw;
4144 struct lysp_feature *feat;
4145
Radek Krejci2c4e7172018-10-19 15:56:26 +02004146 LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004147
4148 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004149 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004150 INSERT_WORD(ctx, buf, feat->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004151
4152 CHECK_UNIQUENESS(ctx, *features, name, "feature", feat->name);
4153
Radek Krejci6d6556c2018-11-08 09:37:45 +01004154 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004155 switch (kw) {
4156 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004157 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 +02004158 break;
4159 case YANG_IF_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004160 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 +02004161 break;
4162 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004163 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 +02004164 break;
4165 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004166 LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004167 break;
4168 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004169 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004170 break;
4171 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004172 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
Radek Krejci2c02f3e2018-10-16 10:54:38 +02004173 return LY_EVALID;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004174 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004175 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004176 return ret;
4177}
4178
Michal Vaskoea5abea2018-09-18 13:10:54 +02004179/**
4180 * @brief Parse the identity statement.
4181 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004182 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004183 * @param[in,out] data Data to read from, always moved to currently handled character.
4184 * @param[in,out] identities Identities to add to.
4185 *
4186 * @return LY_ERR values.
4187 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004188static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004189parse_identity(struct ly_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004190{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004191 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004192 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004193 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004194 enum yang_keyword kw;
4195 struct lysp_ident *ident;
4196
Radek Krejci2c4e7172018-10-19 15:56:26 +02004197 LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004198
4199 /* get value */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004200 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004201 INSERT_WORD(ctx, buf, ident->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004202
4203 CHECK_UNIQUENESS(ctx, *identities, name, "identity", ident->name);
4204
Radek Krejci6d6556c2018-11-08 09:37:45 +01004205 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004206 switch (kw) {
4207 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004208 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 +02004209 break;
4210 case YANG_IF_FEATURE:
Radek Krejci10113652018-11-14 16:56:50 +01004211 YANG_CHECK_STMTVER_RET(ctx, "if-feature", "identity");
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004212 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 +02004213 break;
4214 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004215 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 +02004216 break;
4217 case YANG_STATUS:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004218 LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004219 break;
4220 case YANG_BASE:
Radek Krejci10113652018-11-14 16:56:50 +01004221 if (ident->bases && ctx->mod->version < 2) {
4222 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
4223 return LY_EVALID;
4224 }
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004225 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 +02004226 break;
4227 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004228 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004229 break;
4230 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004231 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004232 return LY_EVALID;
4233 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004234 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004235 return ret;
4236}
4237
Michal Vaskoea5abea2018-09-18 13:10:54 +02004238/**
4239 * @brief Parse the module or submodule statement.
4240 *
Radek Krejci44ceedc2018-10-02 15:54:31 +02004241 * @param[in] ctx yang parser context for logging.
Michal Vaskoea5abea2018-09-18 13:10:54 +02004242 * @param[in,out] data Data to read from, always moved to currently handled character.
4243 * @param[in,out] mod Module to write to.
4244 *
4245 * @return LY_ERR values.
4246 */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004247static LY_ERR
Radek Krejci44ceedc2018-10-02 15:54:31 +02004248parse_sub_module(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *mod)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004249{
4250 LY_ERR ret = 0;
4251 char *buf, *word;
Radek Krejciefd22f62018-09-27 11:47:58 +02004252 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004253 enum yang_keyword kw, prev_kw = 0;
4254 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
Radek Krejcie9e987e2018-10-31 12:50:27 +01004255 struct lysp_module *dup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004256
4257 /* (sub)module name */
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004258 LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len));
Radek Krejci44ceedc2018-10-02 15:54:31 +02004259 INSERT_WORD(ctx, buf, mod->name, word, word_len);
Radek Krejcifaa1eac2018-10-30 14:34:55 +01004260
Radek Krejci6d6556c2018-11-08 09:37:45 +01004261 YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
Michal Vasko7fbc8162018-09-17 10:35:16 +02004262
Radek Krejcie3846472018-10-15 15:24:51 +02004263#define CHECK_ORDER(SECTION) \
4264 if (mod_stmt > SECTION) {LOGVAL_YANG(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
4265
Michal Vasko7fbc8162018-09-17 10:35:16 +02004266 switch (kw) {
4267 /* module header */
4268 case YANG_NAMESPACE:
4269 case YANG_PREFIX:
4270 if (mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004271 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004272 return LY_EVALID;
4273 }
Radek Krejcie3846472018-10-15 15:24:51 +02004274 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4275 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004276 case YANG_BELONGS_TO:
Radek Krejcie3846472018-10-15 15:24:51 +02004277 if (!mod->submodule) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004278 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004279 return LY_EVALID;
4280 }
Radek Krejcie3846472018-10-15 15:24:51 +02004281 CHECK_ORDER(Y_MOD_MODULE_HEADER);
4282 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004283 case YANG_YANG_VERSION:
Radek Krejcie3846472018-10-15 15:24:51 +02004284 CHECK_ORDER(Y_MOD_MODULE_HEADER);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004285 break;
4286 /* linkage */
4287 case YANG_INCLUDE:
4288 case YANG_IMPORT:
Radek Krejcie3846472018-10-15 15:24:51 +02004289 CHECK_ORDER(Y_MOD_LINKAGE);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004290 break;
4291 /* meta */
4292 case YANG_ORGANIZATION:
4293 case YANG_CONTACT:
4294 case YANG_DESCRIPTION:
4295 case YANG_REFERENCE:
Radek Krejcie3846472018-10-15 15:24:51 +02004296 CHECK_ORDER(Y_MOD_META);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004297 break;
4298
4299 /* revision */
4300 case YANG_REVISION:
Radek Krejcie3846472018-10-15 15:24:51 +02004301 CHECK_ORDER(Y_MOD_REVISION);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004302 break;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004303 /* body */
4304 case YANG_ANYDATA:
4305 case YANG_ANYXML:
4306 case YANG_AUGMENT:
4307 case YANG_CHOICE:
4308 case YANG_CONTAINER:
4309 case YANG_DEVIATION:
4310 case YANG_EXTENSION:
4311 case YANG_FEATURE:
4312 case YANG_GROUPING:
4313 case YANG_IDENTITY:
4314 case YANG_LEAF:
4315 case YANG_LEAF_LIST:
4316 case YANG_LIST:
4317 case YANG_NOTIFICATION:
4318 case YANG_RPC:
4319 case YANG_TYPEDEF:
4320 case YANG_USES:
4321 case YANG_CUSTOM:
4322 mod_stmt = Y_MOD_BODY;
4323 break;
4324 default:
4325 /* error handled in the next switch */
4326 break;
4327 }
Radek Krejcie3846472018-10-15 15:24:51 +02004328#undef CHECK_ORDER
Michal Vasko7fbc8162018-09-17 10:35:16 +02004329
Radek Krejcie3846472018-10-15 15:24:51 +02004330 prev_kw = kw;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004331 switch (kw) {
4332 /* module header */
4333 case YANG_YANG_VERSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004334 LY_CHECK_RET(parse_yangversion(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004335 break;
4336 case YANG_NAMESPACE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004337 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 +02004338 break;
4339 case YANG_PREFIX:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004340 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 +02004341 LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004342 break;
4343 case YANG_BELONGS_TO:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004344 LY_CHECK_RET(parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004345 break;
4346
4347 /* linkage */
4348 case YANG_INCLUDE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004349 LY_CHECK_RET(parse_include(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004350 break;
4351 case YANG_IMPORT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004352 LY_CHECK_RET(parse_import(ctx, data, mod));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004353 break;
4354
4355 /* meta */
4356 case YANG_ORGANIZATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004357 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 +02004358 break;
4359 case YANG_CONTACT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004360 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 +02004361 break;
4362 case YANG_DESCRIPTION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004363 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 +02004364 break;
4365 case YANG_REFERENCE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004366 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 +02004367 break;
4368
4369 /* revision */
4370 case YANG_REVISION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004371 LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004372 break;
4373
4374 /* body */
4375 case YANG_ANYDATA:
Radek Krejci10113652018-11-14 16:56:50 +01004376 YANG_CHECK_STMTVER_RET(ctx, "anydata", mod->submodule ? "submodule" : "module");
4377 /* fall through */
Michal Vasko7fbc8162018-09-17 10:35:16 +02004378 case YANG_ANYXML:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004379 LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004380 break;
4381 case YANG_CHOICE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004382 LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004383 break;
4384 case YANG_CONTAINER:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004385 LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004386 break;
4387 case YANG_LEAF:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004388 LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004389 break;
4390 case YANG_LEAF_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004391 LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004392 break;
4393 case YANG_LIST:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004394 LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004395 break;
4396 case YANG_USES:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004397 LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004398 break;
4399
4400 case YANG_AUGMENT:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004401 LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004402 break;
4403 case YANG_DEVIATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004404 LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004405 break;
4406 case YANG_EXTENSION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004407 LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004408 break;
4409 case YANG_FEATURE:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004410 LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004411 break;
4412 case YANG_GROUPING:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004413 LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004414 break;
4415 case YANG_IDENTITY:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004416 LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004417 break;
4418 case YANG_NOTIFICATION:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004419 LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004420 break;
4421 case YANG_RPC:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004422 LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004423 break;
4424 case YANG_TYPEDEF:
Radek Krejcibbe09a92018-11-08 09:36:54 +01004425 LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004426 break;
4427 case YANG_CUSTOM:
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004428 LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
Michal Vasko7fbc8162018-09-17 10:35:16 +02004429 break;
4430
4431 default:
Radek Krejci44ceedc2018-10-02 15:54:31 +02004432 LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), mod->submodule ? "submodule" : "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004433 return LY_EVALID;
4434 }
Michal Vasko7fbc8162018-09-17 10:35:16 +02004435 }
Radek Krejcic59bc972018-09-17 16:13:06 +02004436 LY_CHECK_RET(ret);
Radek Krejci6d6556c2018-11-08 09:37:45 +01004437checks:
Michal Vasko7fbc8162018-09-17 10:35:16 +02004438 /* mandatory substatements */
4439 if (mod->submodule) {
4440 if (!mod->belongsto) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004441 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "belongs-to", "submodule");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004442 return LY_EVALID;
4443 }
4444 } else {
4445 if (!mod->ns) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004446 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "namespace", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004447 return LY_EVALID;
4448 } else if (!mod->prefix) {
Radek Krejci44ceedc2018-10-02 15:54:31 +02004449 LOGVAL_YANG(ctx, LY_VCODE_MISSTMT, "prefix", "module");
Michal Vasko7fbc8162018-09-17 10:35:16 +02004450 return LY_EVALID;
4451 }
4452 }
4453
Radek Krejcie9e987e2018-10-31 12:50:27 +01004454 /* submodules share the namespace with the module names, so there must not be
4455 * a submodule of the same name in the context, no need for revision matching */
4456 dup = ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL);
4457 if (dup && (!mod->submodule || strcmp(dup->belongsto, mod->belongsto))) {
4458 LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
4459 mod->submodule ? "submodules" : "module and submodule", mod->name);
4460 return LY_EVALID;
4461 }
4462
Michal Vasko7fbc8162018-09-17 10:35:16 +02004463 return ret;
4464}
4465
Radek Krejcid4557c62018-09-17 11:42:09 +02004466LY_ERR
Radek Krejcibbe09a92018-11-08 09:36:54 +01004467yang_parse(struct ly_parser_ctx *context, const char *data, struct lysp_module **mod_p)
Michal Vasko7fbc8162018-09-17 10:35:16 +02004468{
Radek Krejci6d9b9b52018-11-02 12:43:39 +01004469 LY_ERR ret = LY_SUCCESS;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004470 char *word, *buf;
Radek Krejciefd22f62018-09-27 11:47:58 +02004471 size_t word_len;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004472 enum yang_keyword kw;
Radek Krejci0c2cf322018-10-13 08:02:30 +02004473 struct lysp_module *mod = NULL;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004474
4475 /* "module"/"submodule" */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004476 ret = get_keyword(context, &data, &kw, &word, &word_len);
4477 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004478
4479 if ((kw != YANG_MODULE) && (kw != YANG_SUBMODULE)) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004480 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
Radek Krejcic59bc972018-09-17 16:13:06 +02004481 ly_stmt2str(kw));
Radek Krejcibbe09a92018-11-08 09:36:54 +01004482 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004483 }
4484
4485 mod = calloc(1, sizeof *mod);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004486 LY_CHECK_ERR_GOTO(!mod, LOGMEM(context->ctx), cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004487 if (kw == YANG_SUBMODULE) {
4488 mod->submodule = 1;
4489 }
Radek Krejcibbe09a92018-11-08 09:36:54 +01004490 mod->parsing = 1;
4491 mod->ctx = context->ctx;
4492 context->mod = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004493
4494 /* substatements */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004495 ret = parse_sub_module(context, &data, mod);
4496 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004497
4498 /* read some trailing spaces or new lines */
Radek Krejcibbe09a92018-11-08 09:36:54 +01004499 ret = get_argument(context, &data, Y_MAYBE_STR_ARG, &word, &buf, &word_len);
4500 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko7fbc8162018-09-17 10:35:16 +02004501
4502 if (word) {
Radek Krejcibbe09a92018-11-08 09:36:54 +01004503 LOGVAL_YANG(context, LYVE_SYNTAX, "Invalid character sequence \"%.*s\", expected end-of-file.",
Michal Vasko7fbc8162018-09-17 10:35:16 +02004504 word_len, word);
4505 free(buf);
Radek Krejcibbe09a92018-11-08 09:36:54 +01004506 goto cleanup;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004507 }
4508 assert(!buf);
4509
Radek Krejcibbe09a92018-11-08 09:36:54 +01004510 mod->parsing = 0;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004511 *mod_p = mod;
Michal Vasko7fbc8162018-09-17 10:35:16 +02004512
Radek Krejcibbe09a92018-11-08 09:36:54 +01004513cleanup:
4514 if (ret) {
4515 lysp_module_free(mod);
4516 }
4517
Michal Vasko7fbc8162018-09-17 10:35:16 +02004518 return ret;
4519}